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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07b3cc0e62a206f392a32139dd069289f720c19e3b00b9fd09ed47bfa6a814bc
4
- data.tar.gz: 5102854abcb5b29ee39b8b45323b5a48b874ea7f149509025a8bc801b51fb337
3
+ metadata.gz: 5513321d2ace0e5e35b6b806fd04f8421e41d713a49667511c278309892a3ec8
4
+ data.tar.gz: b440aca95a39f41a04375a879b917fd153e6277bba6386a1f637e87c2288f225
5
5
  SHA512:
6
- metadata.gz: 7c8841943da9eab5cbbc6be160b76a54d333537fee1ed983d7f9c4dace82029b9f6f8f3d9a57389baedc35866ac76ffa74e3b81037c575396b5fe480a4eb1c60
7
- data.tar.gz: c9bf331909c4cf19c429986fb75a53c40d98feb01c198b4bcfd613c132fe03badd5dc8e15a67024fea124a5646ddaa2da5737f4d5b855478fcbcbb50dba44c96
6
+ metadata.gz: e318b100521c095c1ee8c0962e5108ffe5595281bc9261de0cf8460306c4144b9c5465ef48c6a455c923175b1bc027bcee34d90ea127f5c201d882b427c95169
7
+ data.tar.gz: 1fede9423b4f0dfd0b95a15d7be5ee3b651d0dfdab3b7430f7f4a3f4292e343c8c9c03babbc8c9d52412a76d38914405190fcf37bdd0ab6090f3d27b005daf1c
data/exe/hecks CHANGED
@@ -26,13 +26,6 @@ if File.exist?(File.expand_path("../hecks.gemspec", __dir__)) && File.exist?(gem
26
26
  end
27
27
  end
28
28
 
29
- # The names the gem has always shipped keep their positional forms.
30
- LEGACY = %w[run docs narrate ir stores model_check smoke_test project_diagrams project_cli mcp].freeze
31
- if LEGACY.include?(ARGV.first)
32
- require "hecks/cli"
33
- exit Hecks::CLI.start(ARGV) unless Hecks::CLI.launcher_form?(ARGV)
34
- end
35
-
36
29
  # These commands keep nothing worth a database, so they run on Memory unless told otherwise.
37
30
  # A person is at them: they wait for their result, say why when they are refused, and print
38
31
  # no record when they end well.
@@ -40,17 +33,30 @@ MEMORY_COMMANDS = %w[console init interview].freeze
40
33
  ENV["HECKS_ENVIRONMENT"] ||= "memory" if MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))
41
34
  ARGV << "--wait" if MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!")) && !ARGV.include?("--wait")
42
35
 
36
+ # A command a ledger answers boots that ledger's directory, not this domain's.
37
+ ledger = { "quality_control" => "qa/bluebook" }.fetch(ARGV.first, nil)
38
+ ARGV.shift if ledger
39
+
43
40
  require "hecks"
41
+ # Every secret a world hands an adapter is masked in whatever this process prints.
42
+ Hecks::Secrets.guard!
44
43
 
45
44
  # Usage is answered from the projected bluebook alone: no adapter is bound and no
46
45
  # database is opened. Only a line that runs a command boots the domain,
47
46
  # and it boots from what the usage check already loaded.
48
- domain = File.expand_path("../lib/hecks/hecks", __dir__)
47
+ domain = File.expand_path(ledger ? "../#{ledger}" : "../lib/hecks/hecks", __dir__)
49
48
  program = "hecks"
50
49
  described = begin
51
50
  Hecks.describe(domain)
52
51
  rescue StandardError => e
53
- abort "cannot open Hecks: #{e.message.lines.first.strip}"
52
+ abort "cannot open Hecks: #{e.message.strip}"
53
+ end
54
+
55
+ # `hecks usage` reads the local record of what this launcher ran; it boots nothing.
56
+ if ARGV.first == "usage"
57
+ known = Hecks::Adapters::Driving::CliRunner.known_names(runtime: described, program: program)
58
+ puts Hecks::Adapters::Driving::UsageLog.summary(known: known)
59
+ exit 0
54
60
  end
55
61
 
56
62
  text, status, reason = Hecks::Adapters::Driving::CliRunner.usage(
@@ -60,13 +66,13 @@ unless text
60
66
  runtime = begin
61
67
  Hecks::Adapters::Driving::LauncherOptions.quietly(hold: MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))) { Hecks.boot_described(described, install_driving: false) }
62
68
  rescue StandardError => e
63
- abort "cannot open Hecks: #{e.message.lines.first.strip}"
69
+ abort "cannot open Hecks: #{e.message.strip}"
64
70
  end
65
71
  # A question the world lists under `streams`, given `--stream`, tails until interrupted.
66
72
  streamed = Hecks::Adapters::Driving::CliRunner.stream(runtime: runtime, argv: ARGV, program: program)
67
73
  exit streamed unless streamed.nil?
68
74
  text, status, reason = Hecks::Adapters::Driving::CliRunner.call(
69
- runtime: runtime, argv: ARGV, program: program
75
+ runtime: runtime, argv: ARGV, program: program, usage_log: true
70
76
  )
71
77
  end
72
78
  # A `--wait` run that failed answers its settled record on stdout, so `| jq` reads it
@@ -87,4 +93,5 @@ if reason
87
93
  exit status
88
94
  end
89
95
  exit 0 if status.zero? && MEMORY_COMMANDS.include?(ARGV.first.to_s.chomp("!"))
90
- status.zero? ? puts(text) : abort(text)
96
+ status.zero? ? puts(text) : warn(text)
97
+ exit status
@@ -84,8 +84,8 @@ module Hecks
84
84
 
85
85
  def unwrap(stdout)
86
86
  envelope = JSON.parse(stdout)
87
- result = envelope["result"]
88
- raise Ports::Agent::ValidationError, "no \"result\" in the claude envelope: #{stdout}" unless result
87
+ result = envelope["result"] if envelope.is_a?(Hash)
88
+ raise Ports::Agent::ValidationError, "no \"result\" in the claude envelope: #{stdout}" unless result.is_a?(String)
89
89
 
90
90
  JSON.parse(result)
91
91
  rescue JSON::ParserError => e
@@ -2,6 +2,8 @@ require_relative "../../vocabulary"
2
2
  require_relative "../../ports/loading"
3
3
  require_relative "../../sentence_form"
4
4
  require_relative "folder_overlay"
5
+ require_relative "worktree_overlay"
6
+ require_relative "../../module_folders"
5
7
 
6
8
  module Hecks
7
9
  module Adapters
@@ -130,10 +132,17 @@ module Hecks
130
132
  return unless File.directory?(directory)
131
133
 
132
134
  patterns.each do |pattern|
133
- Dir[File.join(directory, pattern)].reject { |file| left_to_overlay?(file, pattern) }.each { |file| load_file(file) }
135
+ files_matching(directory, pattern).reject { |file| left_to_overlay?(file, pattern) }.each { |file| load_file(file) }
134
136
  end
135
137
  end
136
138
 
139
+ # The files `pattern` names under `directory`; the bluebooks of its module folders follow the
140
+ # directory's own (see ModuleFolders).
141
+ def files_matching(directory, pattern)
142
+ found = Dir[File.join(directory, pattern)]
143
+ found + ModuleFolders.files(directory, pattern.delete_prefix("*"))
144
+ end
145
+
137
146
  # Resolves a domain path to the directory that actually holds its bluebook files.
138
147
  #
139
148
  # @param path [String] a domain directory, holding either a `bluebook/` subdirectory or
@@ -16,6 +16,18 @@ module Hecks
16
16
  # The name of a file that is local: a `.local.hecksagon` or a `.local.world`.
17
17
  LOCAL_FILE_NAME = /\.local\.(hecksagon|world)\z/
18
18
 
19
+ # Runs a block with no overlay loaded at all, so a domain read inside it holds only what is
20
+ # committed: the same on every checkout and in CI, whatever local files this one keeps.
21
+ #
22
+ # @return [Object] the block's value
23
+ def self.committed_only
24
+ held = Thread.current[:hecks_committed_only]
25
+ Thread.current[:hecks_committed_only] = true
26
+ yield
27
+ ensure
28
+ Thread.current[:hecks_committed_only] = held
29
+ end
30
+
19
31
  # Loads the copy's own overlay, then its local files (beside the domain, then in the working
20
32
  # directory), then an environment's overlay, each `.hecksagon` then `.world`, when present.
21
33
  # The environment loads last, so `memory` still wins over a local database.
@@ -24,6 +36,9 @@ module Hecks
24
36
  # @param environment [String, nil] the environment name; nil loads no named overlay
25
37
  # @return [void]
26
38
  def load_overlay(directory, environment)
39
+ return if Thread.current[:hecks_committed_only]
40
+
41
+ WorktreeOverlay.warn_once(directory)
27
42
  load_each(directory, overlay_files(LOCAL_OVERLAY))
28
43
  [directory, Dir.pwd].uniq.each { |where| load_each(where, LOCAL_FILES) }
29
44
  load_each(directory, overlay_files(environment)) if environment && environment != LOCAL_OVERLAY
@@ -133,7 +133,7 @@ module Hecks
133
133
  # @param id [String, Object] the record's identity, compared as `id.to_s`
134
134
  # @return [Boolean] true when a record was found and deleted, false when there was none
135
135
  # and nothing was journaled
136
- def delete(id) # rubocop:disable Naming/PredicateMethod -- the repository port's verb, answering whether a record existed
136
+ def delete(id)
137
137
  return false unless find(id)
138
138
 
139
139
  entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
@@ -30,7 +30,7 @@ module Hecks
30
30
  # @param key_reference [String] the opaque reference {#issue} returned
31
31
  # @return [Boolean] true when a key was held and is now gone; false when this
32
32
  # reference was already destroyed, or never issued
33
- def destroy(key_reference:) = !(@keys ||= {}).delete(key_reference).nil? # rubocop:disable Naming/PredicateMethod
33
+ def destroy(key_reference:) = !(@keys ||= {}).delete(key_reference).nil?
34
34
 
35
35
  # Resets the vault to empty, forgetting every key this process ever issued.
36
36
  #
@@ -26,7 +26,7 @@ module Hecks
26
26
  # @param id [Integer] the row id `outbox_enqueue` assigned
27
27
  # @return [Boolean] true when the row was pending and is now claimed; false when it is
28
28
  # unknown or not pending
29
- def outbox_claim(id) # rubocop:disable Naming/PredicateMethod
29
+ def outbox_claim(id)
30
30
  row = outbox_row(id)
31
31
  return false unless row&.pending?
32
32
 
@@ -42,7 +42,7 @@ module Hecks
42
42
  # not validated here
43
43
  # @param error [String, nil] the failure description, or nil to clear it
44
44
  # @return [Boolean] true when the row exists and was updated; false when no row has `id`
45
- def outbox_settle(id, status:, error: nil) # rubocop:disable Naming/PredicateMethod
45
+ def outbox_settle(id, status:, error: nil)
46
46
  row = outbox_row(id) or return false
47
47
  row.status = status.to_s
48
48
  row.error = error
@@ -0,0 +1,25 @@
1
+ require_relative "../../../ports/persistence/stored_name_guard"
2
+
3
+ module Hecks
4
+ module Adapters
5
+ class Postgres
6
+ # Reads how many rows a table holds before any table is created, for the stored-name guard.
7
+ module NameGuard
8
+ private
9
+
10
+ def refuse_orphaned_rows!
11
+ Ports::Persistence::StoredNameGuard.check!(@aggregate, row_count: method(:rows_under))
12
+ end
13
+
14
+ def rows_under(name)
15
+ [name, "#{name}_entries"].sum { |table| table_rows(table) }
16
+ end
17
+
18
+ def table_rows(table)
19
+ exists = pg_exec_params("SELECT to_regclass($1) AS found", [quote_ident(table)])[0]["found"]
20
+ exists ? pg_exec("SELECT COUNT(*) AS n FROM #{quote_ident(table)}")[0]["n"].to_i : 0
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -83,7 +83,7 @@ module Hecks
83
83
  # @param key [String] the dispatch key a saga leg stamped on the command
84
84
  # @return [Boolean] true when the key was new and is now held; false when already held
85
85
  # @raise [PG::Error] if the insert fails
86
- def dispatch_claim(key) # rubocop:disable Naming/PredicateMethod -- the claim port's verb
86
+ def dispatch_claim(key)
87
87
  pg_exec_params("INSERT INTO hecks_dispatch_claims (claim_key) VALUES ($1) ON CONFLICT DO NOTHING " \
88
88
  "RETURNING claim_key", [key]).ntuples.positive?
89
89
  end
@@ -94,7 +94,7 @@ module Hecks
94
94
  # @return [Boolean] true when the row was pending and is now claimed; false when it is
95
95
  # unknown or another claimer got there first
96
96
  # @raise [PG::Error] if the update fails
97
- def outbox_claim(id) # rubocop:disable Naming/PredicateMethod
97
+ def outbox_claim(id)
98
98
  pg_exec_params(
99
99
  "UPDATE hecks_outbox SET status = 'claimed', attempts = attempts + 1, claimed_at = now() " \
100
100
  "WHERE id = $1 AND status = 'pending'",
@@ -111,7 +111,7 @@ module Hecks
111
111
  # @param error [String, nil] the failure description, or nil to store NULL
112
112
  # @return [Boolean] true when exactly one row was updated; false when no row has `id`
113
113
  # @raise [PG::Error] if the update fails
114
- def outbox_settle(id, status:, error: nil) # rubocop:disable Naming/PredicateMethod
114
+ def outbox_settle(id, status:, error: nil)
115
115
  pg_exec_params(
116
116
  "UPDATE hecks_outbox SET status = $2, error = $3, settled_at = now() WHERE id = $1",
117
117
  [id, status.to_s, error]
@@ -104,7 +104,7 @@ module Hecks
104
104
  # @param id [String, Object] the aggregate identity, journalled as `id.to_s`
105
105
  # @return [Boolean] always true
106
106
  # @raise [PG::Error] if either statement fails; the transaction is rolled back
107
- def delete(id) # rubocop:disable Naming/PredicateMethod -- the repository port's verb, not a question
107
+ def delete(id)
108
108
  entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
109
109
  transaction do
110
110
  append(entry)
@@ -12,7 +12,7 @@ module Hecks
12
12
  # transaction. The owning thread re-enters freely, so a nested `transaction` joins the open
13
13
  # one, whichever aggregate's adapter opened it.
14
14
  class PostgresSharedConnection
15
- REGISTRY = {} # rubocop:disable Style/MutableConstant
15
+ REGISTRY = {}
16
16
  REGISTRY_LOCK = Mutex.new
17
17
  private_constant :REGISTRY, :REGISTRY_LOCK
18
18
 
@@ -2,6 +2,7 @@ require "json"
2
2
 
3
3
  require_relative "sql_query_builder"
4
4
  require_relative "postgres/schema_builder"
5
+ require_relative "postgres/name_guard"
5
6
  require_relative "postgres/codec"
6
7
  require_relative "postgres/dialect"
7
8
  require_relative "postgres/events"
@@ -29,6 +30,7 @@ module Hecks
29
30
  class Postgres
30
31
  include SqlQueryBuilder
31
32
  include SchemaBuilder
33
+ include NameGuard
32
34
  include Codec
33
35
  include Repository
34
36
  include Journal
@@ -125,6 +127,7 @@ module Hecks
125
127
  # Scopes saga rows; falls back to the aggregate's storage name when
126
128
  # settings gives no domain (e.g. a directly-instantiated adapter).
127
129
  @domain = settings.fetch(:domain) { aggregate.storage_name }.to_s
130
+ refuse_orphaned_rows!
128
131
  create_tables!
129
132
  end
130
133
 
@@ -3,8 +3,19 @@ require_relative "../../../indifferent_key"
3
3
  module Hecks
4
4
  module Adapters
5
5
  class PostgresEra
6
+ # Connects a boot to its database without provisioning it: the connection selects the declared
7
+ # schema and creates nothing. Only the mint path opens with `PostgresEra.connect_for`, which
8
+ # creates the schema.
9
+ module ReadConnector
10
+ # @param name [String] the domain or aggregate name, used only in refusal messages
11
+ # @param settings [Hash{Symbol, String => Object}] the persistence settings of the boot
12
+ # @return [PG::Connection] an open connection that writes no schema
13
+ def self.connect_for(name, settings) = PostgresEra.connect_for(name, settings, provision: false)
14
+ end
15
+
6
16
  # The steps `PostgresEra#initialize` runs after joining the shared connection: naming the
7
- # journal, resolving the era, and provisioning every table the adapter reads or writes.
17
+ # journal, resolving the era it reads, and reading the field caches that era holds. A boot
18
+ # writes nothing; the mint path provisions everything.
8
19
  module Boot
9
20
  private
10
21
 
@@ -17,28 +28,29 @@ module Hecks
17
28
  ).to_s
18
29
  end
19
30
 
20
- # Coalesce instead of `setting` for the era: the factory always passes `era:`, nil until
21
- # the boot gate resolves it, and nil can never be a real override.
31
+ # Resolves the era this boot reads. A database that holds no era has never been minted, so
32
+ # the boot refuses by name rather than reading an absent lineage.
33
+ #
34
+ # The era is read from the held eras, never written: the factory passes `era:` once the
35
+ # boot gate resolved it, and nil can never be a real override.
22
36
  def resolve_era!(settings)
23
37
  @era = IndifferentKey.read(settings, :era)
24
- @era ||= @lineage.current_era
38
+ held = @lineage.eras
39
+ refuse_unminted! if held.empty?
40
+ @era ||= held.last[:ordinal]
25
41
  # Non-nil only for a held-but-superseded boot. `append` and `atomic_put` refuse on it
26
42
  # because a superuser walks through the RLS fence.
27
43
  @superseded_by = IndifferentKey.read(settings, :superseded_by)
44
+ # True only for a boot whose shape no held era matches and that carries no mint request.
45
+ # It reads the latest era and refuses writes until a mint runs.
46
+ @unminted = IndifferentKey.read(settings, :unminted) == true
28
47
  end
29
48
 
30
- def provision!
31
- # Idempotent self-healing against any boot-ordering surprise.
32
- @lineage.ensure_head_snapshot!(table, @era)
33
- # A superseded boot reads and never reshapes: era 1's head view is not its to restore,
34
- # because a mint has already pointed the view at a later era.
35
- @lineage.ensure_first_head!(table) if @era == 1 && !@superseded_by
36
- # One row-cache table per where-field the aggregate's queries use; `query` consults it
37
- # to skip the head reduction.
38
- @field_caches = ensure_field_caches!
39
- create_event_table!
40
- create_saga_table!
41
- create_outbox_table!
49
+ # @raise [Runtime::WiringError] always: the database holds no era for a boot to read
50
+ def refuse_unminted!
51
+ raise Runtime::WiringError,
52
+ "cannot boot #{@domain}: no era held; the database is unminted, so run the mint entry " \
53
+ "point (`hecks era.hold_first! <domain directory> --confirm`) to provision and hold the first era"
42
54
  end
43
55
  end
44
56
  end
@@ -12,15 +12,32 @@ module Hecks
12
12
  # @param settings [Hash{Symbol, String => Object}] persistence settings; needs `database`
13
13
  # @param directory [String, nil] where `HECKS_SCAFFOLD=1` writes a translation edge
14
14
  # @return [Integer, nil] the ordinal of the era this boot minted, or nil when none
15
- # @raise [Runtime::WiringError] if the database is unreachable or the mint refuses
15
+ # @raise [Runtime::WiringError] if the database is unreachable or the mint refuses, or the
16
+ # binding's `mints_era` and the bluebook's command words disagree
16
17
  # @raise [Bluebook::DSL::Malformed] if a held era's text parses under no grammar
17
18
  def era_check!(registry:, bluebook:, current_text:, settings:, directory: nil)
19
+ Ports::Persistence::MintDoor.check!(bluebook, settings)
18
20
  LineageManager.check!(
19
21
  registry: registry, bluebook: bluebook, current_text: current_text,
20
22
  settings: settings, directory: directory
21
23
  )
22
24
  end
23
25
 
26
+ # What a boot of this bluebook would resolve, read from its own database over a connection
27
+ # that can only read. The boot's `era_check!` records the same answer. See
28
+ # `LineageManager::EraResolution`.
29
+ #
30
+ # @param registry [Runtime::Registry] the loaded registry, for its translation edges
31
+ # @param bluebook [Bluebook::Declaration] the bluebook as it stands
32
+ # @param settings [Hash{Symbol, String => Object}] persistence settings; needs `database`
33
+ # @param directory [String, nil] the domain's bluebook directory
34
+ # @return [LineageManager::EraResolution::Answer]
35
+ # @raise [Runtime::WiringError] if the database is unreachable or a held text was altered
36
+ def era_status(registry:, bluebook:, settings:, directory: nil)
37
+ LineageManager::EraResolution.read(bluebook: bluebook, settings: settings,
38
+ translations: registry.translations, directory: directory)
39
+ end
40
+
24
41
  # Reads one setting under either its Symbol or String spelling.
25
42
  #
26
43
  # Uses `key?` rather than `||` so a stored `false` is not mistaken for an absent key.
@@ -40,13 +57,15 @@ module Hecks
40
57
  #
41
58
  # @param name [String] the domain or aggregate name, used only in refusal messages
42
59
  # @param settings [Hash{Symbol, String => Object}] `database` is a name or `postgres://` URL
60
+ # @param provision [Boolean] whether a declared `schema` that does not exist yet is created;
61
+ # a mint or an owner write passes true, a boot passes false and reads what is there
43
62
  # @return [PG::Connection] an open connection
44
63
  # @raise [Runtime::WiringError] if `database` is missing or Postgres refuses a statement
45
- def connect_for(name, settings)
64
+ def connect_for(name, settings, provision: true)
46
65
  require_pg!(name)
47
66
  declared = declared_database(name, settings)
48
67
  connection = open_connection(declared)
49
- prepare_session!(connection, setting(settings, :schema))
68
+ prepare_session!(connection, setting(settings, :schema), provision: provision)
50
69
  connection
51
70
  rescue StandardError => e
52
71
  # PG is only defined once the gem loads, so the clause cannot name it.
@@ -81,14 +100,15 @@ module Hecks
81
100
 
82
101
  # A declared `schema` means the instance is shared; search_path makes every unqualified
83
102
  # name this adapter and its lineage classes build resolve inside that schema.
84
- def prepare_session!(connection, schema)
103
+ def prepare_session!(connection, schema, provision:)
85
104
  if schema.to_s != ""
86
- # Idempotent: the schema may not exist yet on the first boot.
87
- connection.exec("CREATE SCHEMA IF NOT EXISTS #{connection.quote_ident(schema)}")
105
+ # A mint creates the schema, idempotently; a read leaves it uncreated. An unknown
106
+ # search_path names no relation, so the lineage reads as unminted.
107
+ connection.exec("CREATE SCHEMA IF NOT EXISTS #{connection.quote_ident(schema)}") if provision
88
108
  connection.exec("SET search_path TO #{connection.quote_ident(schema)}")
89
109
  end
90
110
 
91
- # Provisioning re-runs CREATE ... IF NOT EXISTS on every boot; silence the notices.
111
+ # Provisioning runs CREATE ... IF NOT EXISTS on every mint; silence the notices.
92
112
  # Warnings and above still surface.
93
113
  connection.exec("SET client_min_messages = warning")
94
114
  end
@@ -94,14 +94,19 @@ module Hecks
94
94
 
95
95
  def text_literal(text) = "'#{text.to_s.gsub("'", "''")}'"
96
96
 
97
- # Where-fields of the aggregate's and its entities' queries that a cache table can
98
- # represent; order_by-only fields never needed a cache.
99
- def ensure_field_caches!
100
- cached_where_fields.to_h do |field|
101
- [field, @lineage.ensure_field_cache!(table, @era, field, query_expression(field))]
97
+ # The cache tables of this era a boot may read: each cached where-field whose table exists.
98
+ # A boot creates none; the mint that held the era created them.
99
+ #
100
+ # @return [Hash{String => String}] each cached field mapped to its existing cache table
101
+ def existing_field_caches
102
+ cached_where_fields.each_with_object({}) do |field, found|
103
+ name = @lineage.field_cache(table, @era, field)
104
+ found[field] = name if @lineage.table_exists?(name)
102
105
  end
103
106
  end
104
107
 
108
+ # Where-fields of the aggregate's and its entities' queries that a cache table can
109
+ # represent; order_by-only fields never needed a cache.
105
110
  def cached_where_fields
106
111
  fields = declared_queries.flat_map do |q|
107
112
  q.wheres.map do |clause|
@@ -0,0 +1,39 @@
1
+ require_relative "../sql_query_builder"
2
+ require_relative "dialect"
3
+
4
+ module Hecks
5
+ module Adapters
6
+ class PostgresEra
7
+ # Creates and backfills one aggregate's field caches for one era. Only the mint path that
8
+ # compiles an era's head, and the first-era hold, run it; a boot reads the caches that exist.
9
+ class FieldCacheProvisioner
10
+ include SqlQueryBuilder
11
+ include Dialect
12
+
13
+ # @param lineage [Lineage] the owner lineage whose connection the caches are written on
14
+ # @param aggregate [Bluebook::Aggregate] the aggregate whose where-fields are cached
15
+ # @param era [Integer] the ordinal of the era the caches belong to
16
+ def initialize(lineage, aggregate, era)
17
+ @lineage = lineage
18
+ @aggregate = aggregate
19
+ @era = era
20
+ end
21
+
22
+ # Names the aggregate in storage, as the adapter's `table` does.
23
+ #
24
+ # @return [String] the aggregate's snake_case storage name
25
+ def table = @aggregate.storage_name
26
+
27
+ # Creates each cached where-field's table if missing, then backfills it from the era's head.
28
+ #
29
+ # @return [Hash{String => String}] each cached field mapped to its cache table's name
30
+ # @raise [PG::Error] if Postgres refuses the DDL, a source read or an upsert
31
+ def provision!
32
+ cached_where_fields.to_h do |field|
33
+ [field, @lineage.ensure_field_cache!(table, @era, field, query_expression(field))]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -15,10 +15,11 @@ module Hecks
15
15
  #
16
16
  # @param entry [Ports::Persistence::Entry] the save or delete to journal
17
17
  # @return [Ports::Persistence::Entry] the same entry, unchanged
18
- # @raise [Runtime::WiringError] if this boot's era has been superseded by a mint
18
+ # @raise [Runtime::WiringError] if this boot's shape is not minted yet, or its era has been
19
+ # superseded by a mint
19
20
  # @raise [PG::Error] if Postgres refuses a statement, such as the era fence's RLS
20
21
  def append(entry)
21
- refuse_superseded_write!
22
+ refuse_unwritable_boot!(entry)
22
23
  transaction do
23
24
  lock_writes!
24
25
  append_and_project!(entry)
@@ -26,19 +27,20 @@ module Hecks
26
27
  entry
27
28
  end
28
29
 
29
- # Refuses a write from a checkout whose era a later mint has superseded.
30
- # Runs before the transaction so a stale checkout takes no lock; reads stay allowed.
30
+ # Refuses a write from a checkout whose shape no era holds yet, or whose era a later mint
31
+ # has superseded. Runs before the transaction so a stale checkout takes no lock; reads stay
32
+ # allowed. An unminted boot lets through the one entry whose command declared `mints_era
33
+ # true`; a superseded boot refuses that entry too.
31
34
  #
35
+ # @param entry [Ports::Persistence::Entry] the write about to be journaled
32
36
  # @return [nil] when this boot's era is current
33
- # @raise [Runtime::WiringError] if the boot gate marked this era superseded
34
- def refuse_superseded_write!
37
+ # @raise [Runtime::WiringError] if the boot gate left this shape unminted and the entry is
38
+ # not a mint command's record, or marked its era superseded
39
+ def refuse_unwritable_boot!(entry)
40
+ raise Runtime::WiringError, unminted_refusal if @unminted && !entry.mints_era?
35
41
  return unless @superseded_by
36
42
 
37
- raise Runtime::WiringError,
38
- "cannot write #{table} for #{@domain}: this checkout booted era #{@era}, which era " \
39
- "#{@superseded_by} has superseded — its shape was replaced by a mint, and a write here would " \
40
- "land in a partition no newer head reads. Reads still work; pull the current bluebook and " \
41
- "reboot to write again."
43
+ raise Runtime::WiringError, superseded_refusal
42
44
  end
43
45
 
44
46
  # Saves an entry and reports whether it inserted or replaced, decided under the same lock
@@ -48,10 +50,11 @@ module Hecks
48
50
  # @param insert_only [Boolean] when true, an id already in the head is left untouched
49
51
  # @return [Symbol] `:inserted`, `:replaced`, or `:conflicted` when `insert_only` hit a
50
52
  # record
51
- # @raise [Runtime::WiringError] if this boot's era has been superseded by a mint
53
+ # @raise [Runtime::WiringError] if this boot's shape is not minted yet, or its era has been
54
+ # superseded by a mint
52
55
  # @raise [PG::Error] if Postgres refuses a statement
53
56
  def atomic_put(entry, insert_only: false)
54
- refuse_superseded_write!
57
+ refuse_unwritable_boot!(entry)
55
58
  status = nil
56
59
  transaction do
57
60
  lock_writes!
@@ -93,6 +96,42 @@ module Hecks
93
96
 
94
97
  private
95
98
 
99
+ def unminted_refusal
100
+ "cannot write #{table} for #{@domain}: the shape is not minted yet; run the mint entry point. " \
101
+ "This checkout's shape#{compared_labels} is held by no era, and a write here would land in era " \
102
+ "#{@era}, the latest held era, under a shape it does not hold. Reads still work."
103
+ end
104
+
105
+ # The two labels the boot compared, as far as each can be read: the held era's and this
106
+ # checkout's. Empty when neither can.
107
+ def compared_labels
108
+ held = held_label
109
+ current = current_label
110
+ return "" unless held || current
111
+
112
+ " (#{current || "unknown"}, against held era #{@era}'s #{held || "unknown"})"
113
+ end
114
+
115
+ # @return [String, nil] the label of the era this boot reads, or nil when it cannot be read
116
+ def held_label
117
+ @lineage.eras.find { |era| era[:ordinal] == @era }&.fetch(:label, nil)
118
+ rescue PG::Error, Runtime::WiringError
119
+ nil
120
+ end
121
+
122
+ # @return [String, nil] this checkout's shape label, or nil for an aggregate with no owner
123
+ def current_label
124
+ owner = @aggregate.hecks_owner
125
+ owner && Runtime::StorageShape.mint_label(owner)
126
+ end
127
+
128
+ def superseded_refusal
129
+ "cannot write #{table} for #{@domain}: this checkout booted era #{@era}, which era " \
130
+ "#{@superseded_by} has superseded — its shape was replaced by a mint, and a write here would " \
131
+ "land in a partition no newer head reads. Reads still work; pull the current bluebook and " \
132
+ "reboot to write again."
133
+ end
134
+
96
135
  def head_row?(id)
97
136
  !@db.exec_params("SELECT 1 FROM #{quoted_head} WHERE id = $1 LIMIT 1", [id.to_s]).ntuples.zero?
98
137
  end