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,39 @@
1
+ require "hecks/adapters/driving/cli_runner"
2
+ require_relative "index"
3
+ require_relative "scan"
4
+ require_relative "sources"
5
+
6
+ module Hecks
7
+ module CommandNames
8
+ # The check that every launcher name a file invokes is one the launcher accepts.
9
+ #
10
+ # A renamed command leaves its old name in gate rows, workflows, specs and docs, and a gate that
11
+ # runs a name the launcher refuses runs nothing. This reads those places for `exe/hecks <name>`
12
+ # and `hecks <name>` and looks each up in the launcher's own name table, once.
13
+ module Check
14
+ # One invocation the launcher would refuse.
15
+ Finding = Struct.new(:path, :line, :text, :problem) do
16
+ # @return [String] `file:line`, the string, the fault and the nearest valid name
17
+ def to_s
18
+ near = problem.nearest ? "; nearest valid name: #{problem.nearest}" : ""
19
+ "#{path}:#{line}: #{text[0, 120]} -- #{problem.text}#{near}"
20
+ end
21
+ end
22
+
23
+ module_function
24
+
25
+ # @param root [String] the checkout
26
+ # @param scopes [Hash] `CliRunner.name_index`
27
+ # @return [Array<Finding>] every invocation the launcher would refuse, by file then line
28
+ def findings(root:, scopes:)
29
+ index = Index.new(scopes)
30
+ Sources.files(root).flat_map do |path|
31
+ Scan.new(path, File.read(File.join(root, path), encoding: "UTF-8")).calls.filter_map do |call|
32
+ problem = index.problem(call.words)
33
+ Finding.new(path, call.line, call.text, problem) if problem && !Sources.allowed?(call.text)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,67 @@
1
+ module Hecks
2
+ module CommandNames
3
+ # The launcher invocations in a file's text: where each is, and the words typed after it.
4
+ class Extractor
5
+ # One invocation found.
6
+ Call = Struct.new(:line, :text, :words)
7
+
8
+ # `exe/hecks` names the launcher wherever it appears.
9
+ STRONG = %r{exe/hecks(?=\s)\s+(?<rest>[^`"'|;&)>\\]*)}
10
+ # `exe/hecks` as the head of an argument list.
11
+ LISTED = %r{exe/hecks["']\s*,\s*["'](?<rest>[^"']*)}
12
+ # A bare `hecks` counts when a backtick opens it, or a prompt precedes it.
13
+ QUOTED = /(?<=`)hecks\s+(?<rest>[^`"'|;&)>\\]*)/
14
+ PROMPT = /(?:\A|\s)\$\s+hecks\s+(?<rest>[^`"'|;&)>\\]*)/
15
+ # A bare `hecks` that opens a line of shell, in a fence or a shell file.
16
+ SHELL = /\A\s*(?:bundle exec\s+)?hecks\s+(?<rest>[^`"'|;&)>\\]*)/
17
+
18
+ # A word that can be a launcher name, with the punctuation prose puts after it cut off.
19
+ NAME = /\A[A-Za-z_][\w:]*(?:\.\w+)*!?\z/
20
+
21
+ # The punctuation prose puts after a name.
22
+ TRAILING = /[,.;:)\]]+\z/
23
+
24
+ # A name with a regex-escaped dot (`gate_run\.gate!`): a pattern, not a launcher call.
25
+ ESCAPED = /[\w:!]+(?:\\\.[\w!]*)+/
26
+
27
+ # The line marker that excuses an illustrative invocation, on its own line or the one before.
28
+ MARKER = "dead-name-check: skip".freeze
29
+
30
+ # @param shell [Boolean] whether a line may open with a bare `hecks` (a fence, a shell file)
31
+ # @param strong_only [Boolean] whether only `exe/hecks` counts, as in a code comment's prose
32
+ def initialize(shell: false, strong_only: false)
33
+ @shell = shell
34
+ @strong_only = strong_only
35
+ end
36
+
37
+ # @param line [String] one line of text
38
+ # @param number [Integer] its line number
39
+ # @return [Array<Call>] the invocations on it
40
+ def calls(line, number)
41
+ return [] unless line.include?("hecks")
42
+
43
+ text = line.gsub(ESCAPED, "")
44
+ patterns.flat_map { |pattern| text.scan(pattern).flatten }.filter_map { |rest| call(rest, number, line) }
45
+ end
46
+
47
+ private
48
+
49
+ def patterns
50
+ return [STRONG, LISTED] if @strong_only
51
+
52
+ [STRONG, LISTED, QUOTED, PROMPT, (SHELL if @shell)].compact
53
+ end
54
+
55
+ def call(rest, number, line)
56
+ words = words(rest)
57
+ Call.new(number, line.strip, words) unless words.empty?
58
+ end
59
+
60
+ # The leading words of a line that spell a launcher name, after the flags before it.
61
+ def words(rest)
62
+ tokens = rest.split.drop_while { |token| token.start_with?("-") }
63
+ tokens.map { |token| token.sub(TRAILING, "") }.take_while { |token| token.match?(NAME) }.first(3)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+ require "hecks/adapters/driving/cli_runner"
2
+ require_relative "resolution"
3
+
4
+ module Hecks
5
+ module CommandNames
6
+ # The launcher's accepted names, by scope, and what becomes of a typed line.
7
+ class Index
8
+ # Words the launcher answers before it looks a name up.
9
+ PROGRAM_WORDS = %w[help usage search tour completion resume].freeze
10
+
11
+ # @param scopes [Hash{String => Hash}] `CliRunner.name_index`
12
+ def initialize(scopes)
13
+ @scopes = scopes
14
+ end
15
+
16
+ # @param words [Array<String>] the words after the launcher's name
17
+ # @return [Problem, nil] what is wrong with the line, or nil when the launcher accepts it
18
+ def problem(words)
19
+ scope, rest = scope_of(words)
20
+ asking = Adapters::Driving::CliRunner::QUERY_WORDS.include?(rest.first)
21
+ typed = rest.drop(asking ? 1 : 0).first
22
+ return if typed.nil? || free?(scope, typed)
23
+
24
+ Resolution.new(scope, typed, asking).problem
25
+ end
26
+
27
+ private
28
+
29
+ # An attached bluebook's word hands the rest of the line to that bluebook.
30
+ def scope_of(words)
31
+ scope = words.first && !words.first.empty? && @scopes[words.first]
32
+ scope ? [scope, words.drop(1)] : [@scopes.fetch(""), words]
33
+ end
34
+
35
+ def free?(scope, typed)
36
+ PROGRAM_WORDS.include?(typed) || scope["modules"].include?(typed)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,81 @@
1
+ require "hecks/adapters/driving/cli_runner"
2
+
3
+ module Hecks
4
+ module CommandNames
5
+ # What is wrong with a typed line.
6
+ Problem = Struct.new(:text, :nearest)
7
+
8
+ # One typed word looked up the way the launcher looks it up: every spelling through
9
+ # `canonical_name`, the bang rule of `BangRule`, the neighbours of `Suggestions`.
10
+ class Resolution
11
+ RUNNER = Adapters::Driving::CliRunner
12
+
13
+ # The marks a name carries that a plain English word does not.
14
+ NAME_MARKS = /[_.]/
15
+
16
+ # @param scope [Hash] one scope of `CliRunner.name_index`
17
+ # @param typed [String] the word, with its `!` if it has one
18
+ # @param asking [Boolean] whether `query` came before it
19
+ def initialize(scope, typed, asking)
20
+ @scope = scope
21
+ @cli = { names: { command: scope["command"], question: scope["question"] } }
22
+ @typed = typed.chomp("!")
23
+ @bang = typed.end_with?("!")
24
+ @asking = asking
25
+ @name = RUNNER.canonical_name(@cli, @typed)
26
+ end
27
+
28
+ # @return [Problem, nil] nil when the launcher would run the line
29
+ def problem
30
+ return unknown unless command || question
31
+
32
+ bare_command || banged_query || query_of_command
33
+ end
34
+
35
+ private
36
+
37
+ def command = @scope["command"][@name]
38
+
39
+ def question = @scope["question"][@name]
40
+
41
+ def bare_command
42
+ return unless command && !@asking && !@bang
43
+
44
+ Problem.new("#{@typed} is a command and writes; write it as #{@typed}!", "#{command}!")
45
+ end
46
+
47
+ def banged_query
48
+ return unless @bang && !@asking && !command && question
49
+
50
+ Problem.new("#{@typed}! is a query and reads; write it without the !", "query #{question}")
51
+ end
52
+
53
+ def query_of_command
54
+ return unless @asking && !question
55
+
56
+ Problem.new("#{@typed} is a command, not a query", "#{command}!")
57
+ end
58
+
59
+ def unknown
60
+ return if plain? && !homed?
61
+
62
+ near = RUNNER.near_names(@cli, RUNNER.snake_form(@name), @asking).first
63
+ Problem.new("#{@typed} is not a command or query", near && listed(near))
64
+ end
65
+
66
+ # A lone word with no underscore, dot or bang is as likely English as a name.
67
+ def plain? = !@bang && !@typed.match?(NAME_MARKS)
68
+
69
+ # Whether the word is the last part of some name, so a launcher once accepted it bare.
70
+ def homed?
71
+ (@cli[:names][:command].keys + @cli[:names][:question].keys).any? { |key| key.split(".").last == @name }
72
+ end
73
+
74
+ def listed(near)
75
+ return "#{@scope["command"][near]}!" if @scope["command"][near]
76
+
77
+ "query #{@scope["question"][near]}"
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,54 @@
1
+ require_relative "extractor"
2
+
3
+ module Hecks
4
+ module CommandNames
5
+ # One file read for launcher invocations, leaving out the ones marked as illustrative.
6
+ class Scan
7
+ # A fence whose opening line says its content is shown and not meant to run.
8
+ EXCUSED_FENCE = /\b(?:skip|historical|illustrative)\b/
9
+
10
+ # @param path [String] the file's path, relative to the checkout
11
+ # @param text [String] its text
12
+ def initialize(path, text)
13
+ @path = path
14
+ @lines = text.scrub.lines
15
+ @markdown = path.end_with?(".md")
16
+ @ruby = path.end_with?(".rb")
17
+ @shell = !path.end_with?(".rb", ".md", ".bluebook")
18
+ end
19
+
20
+ # @return [Array<Extractor::Call>] the invocations, each as `calls` of the extractor
21
+ def calls
22
+ fence = nil
23
+ @lines.each_with_index.flat_map do |line, index|
24
+ fence = fence_after(fence, line)
25
+ next [] if skipped?(line, index, fence)
26
+
27
+ extractor(fence, line).calls(line, index + 1)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # The open fence after a line: nil outside one, else its opening line.
34
+ def fence_after(fence, line)
35
+ return fence unless @markdown && line.lstrip.start_with?("```")
36
+
37
+ fence ? nil : line
38
+ end
39
+
40
+ def skipped?(line, index, fence)
41
+ return true if line.lstrip.start_with?("```") || excused?(fence)
42
+
43
+ [line, (@lines[index - 1] if index.positive?)].compact.any? { |text| text.include?(Extractor::MARKER) }
44
+ end
45
+
46
+ def excused?(fence) = fence&.match?(EXCUSED_FENCE)
47
+
48
+ # A Ruby comment is prose, so only the launcher's path names a call in it.
49
+ def extractor(fence, line)
50
+ Extractor.new(shell: @shell || !fence.nil?, strong_only: @ruby && line.lstrip.start_with?("#"))
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,73 @@
1
+ module Hecks
2
+ module CommandNames
3
+ # The files whose text shells out to the launcher, and the ones left out.
4
+ module Sources
5
+ # Globs, relative to the checkout, of the files a line may invoke the launcher in.
6
+ INCLUDED = %w[
7
+ .github/workflows/*.yml .github/workflows/*.yaml .github/actions/**/* .githooks/*
8
+ lib/hecks/language/bluebook/vocabulary.bluebook Makefile scripts/**/* spec/**/*.rb
9
+ docs/implemented/**/*.md CLAUDE.md
10
+ lib/**/*.rb qa/**/*.rb qa/**/*.md qa/**/*.sh qa/**/*.yml
11
+ .claude/hooks/* .claude/settings.json .claude/skills/**/*.md .claude/agents/**/*.md
12
+ ].freeze
13
+
14
+ # Exact lines left unflagged. Each is a dead name kept on purpose until a person picks the
15
+ # command that replaces it; remove the entry when that command exists.
16
+ #
17
+ # The headers below are written into committed generated files (diagrams, the Rust syntax and
18
+ # phrase tables, the site routes, the kernel templates) and specs assert them, so renaming
19
+ # one is a regeneration of those files and its own change.
20
+ ALLOWED_LINES = [
21
+ # The mint plan's ledger line has no successor command yet.
22
+ "exe/hecks Maintenance.mint_era! run.value=<run-id>",
23
+ "hecks project_diagrams", "hecks project_parser_table", "hecks project_phrase_table",
24
+ "hecks measure_kernel_coverage",
25
+ # The installed gem's own `hecks vendor`, which a client runs outside this launcher.
26
+ "(the name `hecks vendor` accepts)", "`hecks site site_projection.project_site"
27
+ ].freeze
28
+
29
+ # Paths that record what was once true, so a retired name in them is history, not a fault.
30
+ HISTORICAL = %r{\A(?:docs/decisions/|docs/implemented/decisions/|docs/archive/|CHANGELOG\.md\z)}
31
+
32
+ # A banner in a document's first lines that says it records a moment.
33
+ SNAPSHOT = /\A(?:>\s*)?\*\*Historical snapshot\b/
34
+
35
+ # A line in a document's first lines that excuses the whole file, such as a page that lists
36
+ # the names a rename leaves behind.
37
+ SKIP_FILE = "dead-name-check: skip-file".freeze
38
+
39
+ # How many lines from the top count as "the first lines".
40
+ BANNER_WINDOW = 12
41
+
42
+ module_function
43
+
44
+ # @param root [String] the checkout
45
+ # @return [Array<String>] the paths to scan, relative to `root`, sorted
46
+ def files(root)
47
+ scanned(root).reject { |path| historical?(root, path) }
48
+ end
49
+
50
+ # @return [Array<String>] every file the globs reach, relative to `root`, sorted
51
+ def scanned(root)
52
+ paths = INCLUDED.flat_map { |glob| Dir.glob(File.join(root, glob), File::FNM_DOTMATCH) }
53
+ relative(root, paths.select { |path| File.file?(path) })
54
+ end
55
+
56
+ # @return [Array<String>] the paths below `root`, once each, sorted
57
+ def relative(root, paths) = paths.map { |path| path.delete_prefix("#{root}/") }.uniq.sort
58
+
59
+ # @return [Boolean] whether a path is history: a decision record, the changelog, an archive, a
60
+ # document whose first lines call it a historical snapshot, or one that excuses itself
61
+ def historical?(root, path)
62
+ return true if path.match?(HISTORICAL)
63
+
64
+ File.foreach(File.join(root, path), encoding: "UTF-8").first(BANNER_WINDOW).any? { |line| excused?(line) }
65
+ end
66
+
67
+ # @return [Boolean] whether a line carries one of the allowed strings
68
+ def allowed?(text) = ALLOWED_LINES.any? { |allowed| text.include?(allowed) }
69
+
70
+ def excused?(line) = line.match?(SNAPSHOT) || line.include?(SKIP_FILE)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "command_names/check"
2
+
3
+ module Hecks
4
+ # Reads the places that shell out to the launcher for names the launcher does not accept.
5
+ module CommandNames
6
+ # The clean verdict.
7
+ CLEAN = "every launcher name invoked in workflows, hooks, gate rows, specs and docs is one the launcher accepts".freeze
8
+
9
+ module_function
10
+
11
+ # @param root [String] the checkout
12
+ # @param runtime [#registry] what `Hecks.describe` answers
13
+ # @return [String] the clean verdict
14
+ # @raise [Failure] with a line for each name the launcher would refuse
15
+ def check(root:, runtime:)
16
+ scopes = Adapters::Driving::CliRunner.name_index(runtime: runtime)
17
+ found = Check.findings(root: root, scopes: scopes)
18
+ raise Failure, found.join("\n") unless found.empty?
19
+
20
+ CLEAN
21
+ end
22
+
23
+ # Raised with every finding.
24
+ class Failure < StandardError; end
25
+ end
26
+ end
@@ -35,7 +35,7 @@ module Hecks
35
35
  # @param confirm [String, nil] the confirmation the runner requires, if any
36
36
  # @return [true]
37
37
  # @raise [Busy] when a job is running
38
- def start(kind:, verb:, args: {}, confirm: nil) # rubocop:disable Naming/PredicateMethod
38
+ def start(kind:, verb:, args: {}, confirm: nil)
39
39
  @mutex.synchronize do
40
40
  raise Busy, "a job is already running" if running?
41
41
 
@@ -157,11 +157,18 @@ module Hecks
157
157
  Hecks.boot(File.join(Parse::ROOT, "lib/hecks/hecks"), install_driving: false, environment: "memory")
158
158
  end
159
159
 
160
+ # A safe-listed command writes through the runner only with its bang; the list names bare commands.
161
+ def writing(argv)
162
+ return argv unless argv.first && SAFE_COMMANDS.include?(argv.first)
163
+
164
+ ["#{argv.first}!", *argv.drop(1)]
165
+ end
166
+
160
167
  # @api private
161
168
  def invoke(argv)
162
169
  rt = runtime
163
170
  @lock.synchronize do
164
- Hecks::Adapters::Driving::CliRunner.call(runtime: rt, program: "hecks", argv: argv)
171
+ Hecks::Adapters::Driving::CliRunner.call(runtime: rt, program: "hecks", argv: writing(argv))
165
172
  end
166
173
  end
167
174
  end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+
5
+ module Hecks
6
+ module Corpus
7
+ # A content hash of everything that decides what `hecks regenerate_corpus` writes for some of
8
+ # the corpus's domains: the generator, and each named domain's own sources. A job that reads a
9
+ # few domains of the generated tree keys its cache on those, so a change to any other domain
10
+ # leaves its cache where it was.
11
+ #
12
+ # The hash reads file contents only, never a time, and only tracked files: a bare checkout and
13
+ # one that has already regenerated hash the same. It errs wide, never narrow: a file that might
14
+ # be read is hashed, so a key can move for a change that did not matter, and never stay put for
15
+ # one that did.
16
+ #
17
+ # Hecks::Corpus::GeneratedKey.key(%w[lease_clock nested_pieces]) # => "9c1e..."
18
+ module GeneratedKey
19
+ # Bumped when what the key hashes changes shape, so every saved entry stops matching.
20
+ VERSION = "1"
21
+
22
+ # What the generator is made of, relative to the checkout: the Rust crates it runs, and the
23
+ # Ruby that builds the IR it reads. Every domain's output depends on all of it.
24
+ GENERATOR_INPUTS = %w[
25
+ rust/codegen/**/* rust/build/**/* rust/parser/**/* rust/Cargo.toml rust/src/generated/mod.rs
26
+ lib/hecks/rust_build/**/* lib/hecks/projector/**/* lib/hecks/corpus/**/* lib/hecks/corpus.rb
27
+ lib/hecks/tools/regeneration_run.rb lib/hecks/tools/regeneration_run/**/*
28
+ lib/hecks/bluebook/**/* lib/hecks/language/**/*
29
+ lib/hecks/runtime/**/* lib/hecks/ports/**/* lib/hecks/rust_format.rb rust-toolchain.toml Gemfile.lock
30
+ lib/hecks/*.rb lib/hecks/grammar/**/* lib/hecks/literal/**/*
31
+ lib/hecks/adapters/driven/*.adapter lib/hecks/adapters/driven/folder*
32
+ ].freeze
33
+
34
+ # The generated modules hashed into every key, whichever domains are named: pizzas, whose
35
+ # translations carry SQL only the Ruby toolchain compiles, so it is not a function of its
36
+ # own bluebook alone.
37
+ COMMITTED_OUTPUT = %w[pizzas].freeze
38
+
39
+ # Every bluebook, hecksagon, world and adapter file of the gem: what a domain that attaches a
40
+ # bluebook this key cannot name exactly is hashed against.
41
+ ALL_BLUEBOOK_FILES = %w[lib/hecks/**/*.bluebook lib/hecks/**/*.hecksagon lib/hecks/**/*.world
42
+ lib/hecks/**/adapters/*.adapter].freeze
43
+
44
+ # The one way a hecksagon attaches a gem bluebook or a vendored package, which this key can
45
+ # follow exactly.
46
+ ATTACHES_LINE = /\A\s*attaches\s+"(?<name>\w+)"(?<vendored>,\s*from:\s*:vendor)?\s*(?:#.*)?\z/
47
+
48
+ # Any other line that names an attachment, which this key cannot follow: it hashes wide.
49
+ ATTACHMENT_WORD = /\battaches\b|FrameworkBluebooks\.|\battach!|Framework\.load!/
50
+
51
+ # The files a hecksagon's own text can name an attachment in.
52
+ ATTACHING_FILES = /\.(hecksagon|world|adapter)\z/
53
+
54
+ # The directory of the gem's Ruby, which a bluebook's absolute path is read relative to.
55
+ GEM_LIB = File.expand_path("..", __dir__).freeze
56
+
57
+ # Raised inside this module when an attachment cannot be followed to the files it reads.
58
+ class Unresolved < StandardError; end
59
+
60
+ module_function
61
+
62
+ # The key of the generated output of the named domains.
63
+ #
64
+ # @param names [Array<String>, nil] feature names; nil names every domain
65
+ # @param root [String] the checkout
66
+ # @return [String] the hex digest
67
+ # @raise [UnknownDomain] when a name is not a domain, listing the valid ones
68
+ def key(names = nil, root: ROOT)
69
+ digest(listing(names, root: root))
70
+ end
71
+
72
+ # @param lines [Array<String>] the rows of `listing`
73
+ # @return [String] the hex digest the rows add up to
74
+ def digest(lines) = Digest::SHA256.hexdigest("generated-key-#{VERSION}\n#{lines.join("\n")}")
75
+
76
+ # What `hecks corpus_run.generated_key` answers: the key, with each file hashed above it when
77
+ # they are asked for.
78
+ #
79
+ # @param names [Array<String>, nil] feature names; nil names every domain
80
+ # @param files [Boolean] whether to list each file hashed, with its own digest
81
+ # @param root [String] the checkout
82
+ # @return [String] the lines
83
+ # @raise [UnknownDomain] when a name is not a domain, listing the valid ones
84
+ def report(names = nil, files: false, root: ROOT)
85
+ rows = listing(names, root: root)
86
+ [*(rows if files), digest(rows)].join("\n")
87
+ end
88
+
89
+ # Each file the key hashes, with its own digest, so a reviewer can see why a key moved.
90
+ #
91
+ # @param names [Array<String>, nil] feature names; nil names every domain
92
+ # @param root [String] the checkout
93
+ # @return [Array<String>] `"<sha256> <path>"` rows, sorted by path
94
+ # @raise [UnknownDomain] when a name is not a domain, listing the valid ones
95
+ def listing(names = nil, root: ROOT)
96
+ files(names, root: root).map { |path| "#{Digest::SHA256.file(File.join(root, path)).hexdigest} #{path}" }
97
+ end
98
+
99
+ # @param names [Array<String>, nil] feature names; nil names every domain
100
+ # @param root [String] the checkout
101
+ # @return [Array<String>] the paths the key hashes, relative to the checkout, sorted
102
+ # @raise [UnknownDomain] when a name is not a domain, listing the valid ones
103
+ def files(names = nil, root: ROOT)
104
+ domains = Corpus.rust_domains_named(names, root: root)
105
+ (generator_files(root) + domains.flat_map { |domain| domain_files(domain, root) }).uniq.sort
106
+ end
107
+
108
+ # @return [Array<String>] the generator's files that exist, and the committed generated output
109
+ def generator_files(root)
110
+ globs = GENERATOR_INPUTS + COMMITTED_OUTPUT.map { |feature| "rust/src/generated/#{feature}/**/*" }
111
+ globs.flat_map { |glob| expand(glob, root) }
112
+ end
113
+
114
+ # One domain's own directory and every bluebook it attaches.
115
+ #
116
+ # @param domain [RustDomain] the domain
117
+ # @param root [String] the checkout
118
+ # @return [Array<String>] the paths, relative to the checkout
119
+ def domain_files(domain, root)
120
+ own = expand("#{domain.dir.delete_prefix("#{root}/")}/**/*", root)
121
+ own + attached_files(own, root)
122
+ end
123
+
124
+ # The files of every bluebook the domain's own hecksagons attach, followed through the ports
125
+ # and adapters a bluebook ships. A bluebook this cannot follow exactly widens to all of them.
126
+ #
127
+ # @param own [Array<String>] the domain's own files, relative to the checkout
128
+ # @param root [String] the checkout
129
+ # @return [Array<String>] the bluebook files, relative to the checkout
130
+ def attached_files(own, root)
131
+ follow(names_in(own, root).uniq, root)
132
+ rescue Unresolved
133
+ ALL_BLUEBOOK_FILES.flat_map { |glob| expand(glob, root) }
134
+ end
135
+
136
+ # @param path [String] a hecksagon, world or adapter file, relative to the checkout
137
+ # @param root [String] the checkout
138
+ # @return [Array<String>] the gem bluebooks it attaches, by name
139
+ # @raise [Unresolved] when it names an attachment in a way this does not follow
140
+ def attached_names(path, root)
141
+ File.readlines(File.join(root, path), chomp: true, encoding: "UTF-8").filter_map do |line|
142
+ next if line.strip.start_with?("#") || !line.match?(ATTACHMENT_WORD)
143
+
144
+ match = ATTACHES_LINE.match(line) or raise Unresolved, "#{path}: #{line.strip}"
145
+ match[:name] unless match[:vendored]
146
+ end
147
+ end
148
+
149
+ # Every file of the named bluebooks and of the bluebooks their own hecksagons attach.
150
+ #
151
+ # @param pending [Array<String>] bluebook names still to read
152
+ # @param root [String] the checkout
153
+ # @return [Array<String>] the files, relative to the checkout
154
+ # @raise [Unresolved] when a bluebook is not one the gem carries
155
+ def follow(pending, root)
156
+ files = []
157
+ seen = []
158
+ while (name = pending.shift)
159
+ next if seen.include?(name)
160
+
161
+ seen << name
162
+ files.concat(bluebook = bluebook_paths(name, root))
163
+ pending.concat(names_in(bluebook, root))
164
+ end
165
+ files
166
+ end
167
+
168
+ # @param paths [Array<String>] files relative to the checkout
169
+ # @param root [String] the checkout
170
+ # @return [Array<String>] the bluebooks the hecksagons, worlds and adapters among them attach
171
+ # @raise [Unresolved] when one names an attachment in a way this does not follow
172
+ def names_in(paths, root)
173
+ paths.grep(ATTACHING_FILES).flat_map { |path| attached_names(path, root) }
174
+ end
175
+
176
+ # @param name [String] a bluebook's name
177
+ # @param root [String] the checkout
178
+ # @return [Array<String>] the files attaching it reads, relative to the checkout
179
+ # @raise [Unresolved] when the gem carries no bluebook of that name
180
+ def bluebook_paths(name, root)
181
+ require_relative "../framework_bluebooks"
182
+ FrameworkBluebooks.files_of(name).map do |path|
183
+ raise Unresolved, "#{name}: #{path} is outside the gem" unless path.start_with?("#{GEM_LIB}/")
184
+
185
+ relative = File.join("lib/hecks", path.delete_prefix("#{GEM_LIB}/"))
186
+ File.file?(File.join(root, relative)) ? relative : nil
187
+ end.compact
188
+ rescue Runtime::WiringError => e
189
+ raise Unresolved, e.message
190
+ end
191
+
192
+ # The files a glob finds, relative to the checkout: no directory, and nothing under a Cargo
193
+ # `target`, which a build fills and a bare checkout does not have.
194
+ #
195
+ # @param glob [String] a glob, relative to the checkout
196
+ # @param root [String] the checkout
197
+ # @return [Array<String>] the paths
198
+ def expand(glob, root)
199
+ Dir.glob(glob, File::FNM_DOTMATCH, base: root).select do |path|
200
+ File.file?(File.join(root, path)) && !path.split("/").include?("target") && File.basename(path) != ".DS_Store"
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,34 @@
1
+ module Hecks
2
+ module Corpus
3
+ # How a kind's glob becomes its members: a directory each, or a file each.
4
+ # Extended onto `Corpus`.
5
+ module Listing
6
+ # @return [Array<Member>] the members of one kind: a directory each, or a file each
7
+ # @raise [ArgumentError] if `kind` is not in `KINDS`
8
+ def kind_members(kind, root)
9
+ if (glob = DIRECTORY_KINDS[kind])
10
+ directory_members(kind, root, glob)
11
+ elsif (glob = FILE_KINDS[kind])
12
+ file_members(kind, root, glob)
13
+ else
14
+ raise ArgumentError, "unknown corpus kind #{kind.inspect} — known: #{KINDS.join(", ")}"
15
+ end
16
+ end
17
+
18
+ def directory_members(kind, root, glob)
19
+ directories(root, glob).map { |dir| Member.new(File.basename(dir), kind, dir) }
20
+ end
21
+
22
+ def directories(root, glob) = Dir.glob(File.join(root, glob)).select { |path| File.directory?(path) }.sort
23
+
24
+ # The part of a glob before its first wildcard.
25
+ GLOB_FIXED_PREFIX = /\A[^*]*/
26
+
27
+ def file_members(kind, root, glob)
28
+ prefix = File.join(root, glob[GLOB_FIXED_PREFIX].chomp("/"))
29
+ Dir.glob(File.join(root, glob))
30
+ .map { |file| Member.new(file.delete_prefix("#{prefix}/").delete_suffix(".bluebook"), kind, file) }
31
+ end
32
+ end
33
+ end
34
+ end