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,120 @@
1
+ # The Run kind: an aggregate declared `kind: "Run"` is one request to the codebase tooling, carried
2
+ # out only inside a hecks checkout. It holds the lifecycle every such request shares, the three
3
+ # bookkeeping commands that move it along, the two queries that read how requests ended, and the
4
+ # policies that examine, accept, perform and record it.
5
+ #
6
+ # This file is aggregate-body text in the bluebook's own words. `{Name}` stands for the aggregate's
7
+ # name and `{Stem}` for that name without the kind (`GateRun` has the stem `Gate`). The aggregate's
8
+ # own body is evaluated at the `# body` line, so its attributes, value objects and request commands
9
+ # fall between the lines above and below it.
10
+ attribute :run, RunKey
11
+ attribute :operation, Operation, optional: true
12
+
13
+ value_object "RunKey" do
14
+ attribute :value, String, matches: :present
15
+
16
+ invariant("a run is named") { !value.to_s.empty? }
17
+ end
18
+
19
+ value_object "Operation" do
20
+ attribute :value, String, matches: :present
21
+ end
22
+
23
+ value_object "Switch" do
24
+ attribute :value, Boolean
25
+ end
26
+
27
+ value_object "Report" do
28
+ attribute :value, String
29
+ end
30
+
31
+ # body
32
+
33
+ attribute :checkout, Switch, optional: true
34
+ attribute :report, Report, optional: true
35
+ attribute :refusal, Report, optional: true
36
+ identified_by :run
37
+
38
+ lifecycle :status, default: "requested" do
39
+ mark :failure, "faulted"
40
+ transition "Accept" => "accepted", from: "requested"
41
+ transition "Complete" => "completed", from: "accepted"
42
+ transition "Fault" => "faulted", from: %w[requested accepted]
43
+ mark :terminal, "completed", "faulted"
44
+ end
45
+
46
+ # What the tree reported about itself, held against every request: nothing here runs
47
+ # outside a hecks checkout (hecks.gemspec beside lib/).
48
+ command "Accept" do
49
+ role "System"
50
+ goal "Let a request through only when the working tree is a hecks checkout"
51
+
52
+ reference_to {Name}
53
+ attribute :checkout, Switch, sets: true
54
+
55
+ given("needs a hecks checkout: hecks.gemspec stands beside lib/") { checkout.value }
56
+
57
+
58
+ emits {Stem}Accepted
59
+ end
60
+
61
+ command "Complete" do
62
+ role "System"
63
+ goal "Record that the request was carried out, and what it reported"
64
+
65
+ reference_to {Name}
66
+ attribute :report, Report, sets: true
67
+
68
+
69
+ emits {Stem}Completed
70
+ end
71
+
72
+ command "Fault" do
73
+ role "System"
74
+ goal "Record that the request was refused or could not be carried out, and why"
75
+
76
+ reference_to {Name}
77
+ attribute :refusal, Report, sets: true
78
+
79
+
80
+ emits {Stem}Faulted
81
+ end
82
+
83
+ query "{Stem}Outcome" do
84
+ description "How one request ended: its status, and what it reported or why it failed."
85
+ attribute :run, RunKey
86
+ where(run: :run)
87
+ order_by :run
88
+ end
89
+
90
+ query "{Stem}Faulted" do
91
+ description "Every request that was refused or could not be carried out."
92
+ where(status: "faulted")
93
+ order_by :run
94
+ end
95
+
96
+ policy "Accept{Stem}WhenExamined" do
97
+ on "{Name}.{Stem}Examined"
98
+ trigger {Name}::Accept, with: { checkout: :checkout }
99
+ end
100
+
101
+ policy "Fault{Stem}WhenNotAccepted" do
102
+ on "{Name}.{Stem}Examined"
103
+ where { !checkout.value }
104
+ trigger {Name}::Fault, with: { refusal: "needs a hecks checkout: hecks.gemspec stands beside lib/" }
105
+ end
106
+
107
+ policy "Perform{Stem}WhenAccepted" do
108
+ on "{Name}.{Stem}Accepted"
109
+ ask :perform, with: { run: :run }
110
+ end
111
+
112
+ policy "Record{Stem}Outcome" do
113
+ on "{Name}.{Stem}Answered"
114
+ trigger {Name}::Complete, with: { report: :report }
115
+ end
116
+
117
+ policy "Record{Stem}Fault" do
118
+ on "{Name}.{Stem}Refused"
119
+ trigger {Name}::Fault, with: { refusal: :refusal }
120
+ end
@@ -81,6 +81,11 @@
81
81
  "verb": "Bluebook::Bluebook.Declare",
82
82
  "role": "Language"
83
83
  },
84
+ {
85
+ "scope": "bluebook:bluebook.group",
86
+ "verb": "Bluebook::Bluebook.Group",
87
+ "role": "Language"
88
+ },
84
89
  {
85
90
  "scope": "bluebook:bluebook.normalise",
86
91
  "verb": "Bluebook::Bluebook.Normalise",
@@ -96,6 +101,11 @@
96
101
  "verb": "Bluebook::Command.ActsOn",
97
102
  "role": "Language"
98
103
  },
104
+ {
105
+ "scope": "bluebook:command.address",
106
+ "verb": "Bluebook::Command.Address",
107
+ "role": "Language"
108
+ },
99
109
  {
100
110
  "scope": "bluebook:command.allow",
101
111
  "verb": "Bluebook::Command.Allow",
@@ -31,6 +31,7 @@ Hecks.bluebook "Translation" do
31
31
  attribute :retypes, list_of(TranslationRetype)
32
32
  attribute :derives, list_of(TranslationDerive)
33
33
  attribute :rekeys, list_of(TranslationRekey)
34
+ attribute :splits, list_of(TranslationSplit)
34
35
  attribute :backfills, list_of(TranslationBackfill)
35
36
 
36
37
  # Field names mirror the Struct records in lib/hecks/bluebook/translation.rb, not the
@@ -65,6 +66,12 @@ Hecks.bluebook "Translation" do
65
66
  attribute :to, TranslationName
66
67
  end
67
68
 
69
+ value_object "TranslationSplit" do
70
+ attribute :into, TranslationName
71
+ attribute :keyed_by, TranslationName
72
+ attribute :fields, list_of(TranslationName)
73
+ end
74
+
68
75
  value_object "TranslationBackfill" do
69
76
  attribute :name, TranslationName
70
77
  attribute :default, TranslationLiteralText
@@ -168,6 +175,19 @@ Hecks.bluebook "Translation" do
168
175
  emits "TranslationRekeyToAdded"
169
176
  end
170
177
 
178
+ command "AddSplit" do
179
+ role "Deployment"
180
+ goal "Write rows into another aggregate from this one's rows, keyed by a field both share"
181
+
182
+ attribute :into, TranslationName
183
+ attribute :keyed_by, TranslationName
184
+ attribute :fields, list_of(TranslationName)
185
+
186
+ sets :splits, append: { into: :into, keyed_by: :keyed_by, fields: :fields }
187
+
188
+ emits "TranslationSplitAdded"
189
+ end
190
+
171
191
  command "AddBackfill" do
172
192
  role "Deployment"
173
193
  goal "Name a newly required attribute and the value an existing record reads until written for real"
@@ -194,6 +214,7 @@ Hecks.bluebook "Translation" do
194
214
  attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
195
215
 
196
216
  member word: "rename", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "renames", calls: "rename_impl"
217
+ member word: "split", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "splits", calls: "split_impl"
197
218
  member word: "move", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "moves", calls: "move_impl"
198
219
  member word: "convert", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "converts", calls: "convert_impl"
199
220
  member word: "drop", context: "TranslationAggregate", body: "none", inner: "", opens: "", fills: "drops"
@@ -224,6 +245,9 @@ Hecks.bluebook "Translation" do
224
245
 
225
246
  member keyword: "rename", context: "TranslationAggregate", at: "1", named: "", kind: "symbol", required: "true", fills: "old_name"
226
247
  member keyword: "rename", context: "TranslationAggregate", at: "", named: "to", kind: "symbol", required: "true", fills: "to"
248
+ member keyword: "split", context: "TranslationAggregate", at: "", named: "into", kind: "text", required: "true", fills: "into"
249
+ member keyword: "split", context: "TranslationAggregate", at: "", named: "keyed_by", kind: "text", required: "true", fills: "keyed_by"
250
+ member keyword: "split", context: "TranslationAggregate", at: "", named: "fields", kind: "text", required: "true", fills: "fields"
227
251
  member keyword: "move", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
228
252
  member keyword: "move", context: "TranslationAggregate", at: "", named: "to", kind: "text", required: "true", fills: "to"
229
253
  member keyword: "convert", context: "TranslationAggregate", at: "1", named: "", kind: "text", required: "true", fills: "old_path"
@@ -0,0 +1,31 @@
1
+ module Hecks
2
+ # The module folders of a domain directory (ADR 0163). A folder named for a module holds that
3
+ # module's bluebook beside its name, `deliver/deliver.bluebook`; the bluebooks in them declare
4
+ # the one bluebook the directory's top-level file opens.
5
+ module ModuleFolders
6
+ module_function
7
+
8
+ # @param directory [String] a domain directory
9
+ # @return [Array<String>] the bluebook of each module folder directly under `directory`,
10
+ # sorted by path
11
+ def bluebooks(directory)
12
+ files(directory, ".bluebook")
13
+ end
14
+
15
+ def files(directory, extension)
16
+ Dir.glob(File.join(directory, "*", "*#{extension}")).select { |path| module_file?(path, extension) }.sort
17
+ end
18
+
19
+ # @param directory [String] a domain directory
20
+ # @return [Array<String>] the directory's own bluebooks, then those of its module folders
21
+ def all(directory)
22
+ Dir.glob(File.join(directory, "*.bluebook")) + bluebooks(directory)
23
+ end
24
+
25
+ # Whether a bluebook is named for the folder it sits in.
26
+ # @api private
27
+ def module_file?(path, extension)
28
+ File.basename(path, extension) == File.basename(File.dirname(path))
29
+ end
30
+ end
31
+ end
@@ -23,7 +23,7 @@ module Hecks
23
23
  # shredded or being shredded, is left alone and returns false.
24
24
  #
25
25
  # @return [Boolean] whether a shred was asked for; the record's status says how it ended
26
- def shred!(dispatcher, domain:, subject_id:) # rubocop:disable Naming/PredicateMethod
26
+ def shred!(dispatcher, domain:, subject_id:)
27
27
  provider = dispatcher.registry.provider_of(Bluebook::Capabilities::SUBJECT_KEYS)
28
28
  return false unless provider
29
29
 
@@ -12,7 +12,11 @@ module Hecks
12
12
  # (set by `append` on a live write, or by `entries`/`entries_since` on
13
13
  # a replayed one); nil for an adapter that assigns none. It rides
14
14
  # along so `project` can advance a checkpoint without a second lookup.
15
- Entry = Struct.new(:operation, :id, :state, :mirrors, :sequence, keyword_init: true) do
15
+ #
16
+ # `mints_era` is the one-write allowance a command declared with `mints_era true` holds:
17
+ # only this entry, the command's own record, may be journaled through a boot whose shape no
18
+ # era holds yet. Nothing about it is persisted.
19
+ Entry = Struct.new(:operation, :id, :state, :mirrors, :sequence, :mints_era, keyword_init: true) do
16
20
  # Tells a projecting adapter that this entry writes a record.
17
21
  #
18
22
  # @return [Boolean] true when `operation` is the String `"save"`
@@ -22,6 +26,9 @@ module Hecks
22
26
  #
23
27
  # @return [Boolean] true when `operation` is the String `"delete"`
24
28
  def delete? = operation == "delete"
29
+
30
+ # @return [Boolean] true when the command that wrote this entry declared `mints_era true`
31
+ def mints_era? = mints_era == true
25
32
  end
26
33
 
27
34
  # Makes append-before-projection a port invariant: adapters keep their own durable
@@ -49,6 +56,14 @@ module Hecks
49
56
  "#{adapter.class} does not implement append-only persistence: #{missing.join(", ")}"
50
57
  end
51
58
 
59
+ # Whether the adapter's binding names this command as one whose own record an unminted
60
+ # boot may write (`mints_era` in the world); an adapter with no such binding says no.
61
+ #
62
+ # @param agg [String] the aggregate the command belongs to
63
+ # @param name [String] the command
64
+ # @return [Boolean]
65
+ def mints_era_declared?(agg, name) = adapter.respond_to?(:mints_era_declared?) && adapter.mints_era_declared?(agg, name)
66
+
52
67
  # Reads one record's current projected state from the adapter.
53
68
  #
54
69
  # @param id [String, Object] the record's identity; adapters compare it as `id.to_s`
@@ -183,15 +198,16 @@ module Hecks
183
198
  # Returns an Outcome, not a bare Instance, so callers can check `:saved` vs `:stale`;
184
199
  # `expected_version:` only triggers CAS on an adapter declaring `:optimistic_concurrency`.
185
200
  #
186
- # @param instance [Runtime::Instance] the record to persist; its `state` is shallow
187
- # copied into the entry
201
+ # @param instance [Runtime::Instance] the record to persist; its `state` is shallow copied
188
202
  # @param expected_version [Integer, nil] the version the instance was read at, or nil
189
203
  # for an unconditional write
204
+ # @param mints_era [Boolean] true when the writing command declares `mints_era true`
190
205
  # @return [Persistence::Outcome] status `:saved` or `:stale`; `instance` is the
191
206
  # adapter's projected result on `:saved`, else the instance passed in
192
207
  # @raise [Runtime::WiringError] when the adapter's `append` or `project` refuses
193
- def save(instance, expected_version: nil)
194
- entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
208
+ def save(instance, expected_version: nil, mints_era: false)
209
+ entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup,
210
+ mints_era: mints_era)
195
211
  append(entry)
196
212
  if expected_version && capabilities.include?(:optimistic_concurrency)
197
213
  saved = @adapter.project(entry, expected_version: expected_version)
@@ -208,19 +224,21 @@ module Hecks
208
224
  #
209
225
  # @param instance [Runtime::Instance] the record to persist
210
226
  # @param insert_only [Boolean] true to refuse replacing a record that already exists
227
+ # @param mints_era [Boolean] true when the writing command declares `mints_era true`
211
228
  # @return [Persistence::Outcome] status `:inserted`, `:replaced`, or `:conflicted` when
212
229
  # `insert_only` met an existing record and nothing was written; `instance` is always
213
230
  # the instance passed in
214
231
  # @raise [Runtime::WiringError] if the adapter does not both advertise `:atomic_put`
215
232
  # and implement it
216
233
  # @raise [ArgumentError] if the adapter answers a status outside `Outcome::STATUSES`
217
- def atomic_put(instance, insert_only: false)
234
+ def atomic_put(instance, insert_only: false, mints_era: false)
218
235
  unless capabilities.include?(:atomic_put) && @adapter.respond_to?(:atomic_put)
219
236
  raise Runtime::WiringError,
220
237
  "#{@adapter.class} advertises no atomic_put persistence capability"
221
238
  end
222
239
 
223
- entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
240
+ entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup,
241
+ mints_era: mints_era)
224
242
  status = @adapter.atomic_put(entry, insert_only: insert_only)
225
243
  Outcome.new(status: status, instance: instance)
226
244
  end
@@ -231,7 +249,7 @@ module Hecks
231
249
  # @return [Boolean] true when a record was found and deleted, false when there was
232
250
  # none and nothing was journaled
233
251
  # @raise [Runtime::WiringError] when the adapter's `append` or `project` refuses
234
- def delete(id) # rubocop:disable Naming/PredicateMethod -- the repository port's verb, answering whether a record existed
252
+ def delete(id)
235
253
  return false unless find(id)
236
254
 
237
255
  entry = Entry.new(operation: "delete", id: id.to_s, state: nil)
@@ -80,7 +80,9 @@ module Hecks
80
80
  # @return [Bluebook::Bind] the authoritative bind
81
81
  # @raise [Runtime::WiringError] if the roleless count is not one, or a role is present
82
82
  def authoritative_among(bindings, domain, aggregate)
83
- authoritative = bindings.select { |bind| bind.role.nil? || bind.role.empty? }
83
+ # The same adapter declared again, by a hecksagon that another domain also attaches, is one
84
+ # binding, not an ambiguous second one.
85
+ authoritative = bindings.select { |bind| bind.role.nil? || bind.role.empty? }.uniq(&:adapter)
84
86
  raise ambiguous_binding(domain, aggregate, authoritative) unless authoritative.size == 1
85
87
 
86
88
  roled = bindings - authoritative
@@ -83,7 +83,7 @@ module Hecks
83
83
  module Guarded; end
84
84
 
85
85
  # A per-adapter-class cache, filled lazily under `WRAPPERS_LOCK`; deliberately mutable.
86
- WRAPPERS = {} # rubocop:disable Style/MutableConstant
86
+ WRAPPERS = {}
87
87
  WRAPPERS_LOCK = Mutex.new
88
88
 
89
89
  # Builds, or fetches from the cache, the module that guards one adapter class.
@@ -0,0 +1,74 @@
1
+ require_relative "../../runtime/errors"
2
+
3
+ module Hecks
4
+ module Ports
5
+ module Persistence
6
+ # The commands whose own record an unminted boot may write, as a persistence binding names
7
+ # them: `persisted_by("PostgresEra") { mints_era "Maintenance.MintEra" }` in a world. This is
8
+ # where the allowance lives; the `mints_era true` a command can still carry is read as a
9
+ # fallback, and the two must agree.
10
+ #
11
+ # A name is `Aggregate.Command`. The world may give one name or a list.
12
+ module MintDoor
13
+ module_function
14
+
15
+ # @param settings [Hash{Symbol, String => Object}] a persistence binding's settings
16
+ # @return [Array<String>] the `Aggregate.Command` names the binding declares, else `[]`
17
+ def names(settings)
18
+ Array(settings.transform_keys(&:to_sym)[:mints_era]).map(&:to_s)
19
+ end
20
+
21
+ # @param settings [Hash] a persistence binding's settings
22
+ # @param aggregate_name [String] the aggregate the command belongs to
23
+ # @param command_name [String] the command
24
+ # @return [Boolean] true when the binding names `aggregate_name.command_name`
25
+ def declared?(settings, aggregate_name, command_name)
26
+ names(settings).include?("#{aggregate_name}.#{command_name}")
27
+ end
28
+
29
+ # Checks the binding against the bluebook it serves, before anything is written.
30
+ #
31
+ # A binding that names no command leaves the bluebook word alone. One that does must name
32
+ # only commands the bluebook declares, and every command the bluebook flags with
33
+ # `mints_era true` must be among them, so the two never disagree about who may write.
34
+ #
35
+ # @param bluebook [Bluebook::Declaration] the bluebook the binding serves
36
+ # @param settings [Hash] the binding's settings
37
+ # @return [void]
38
+ # @raise [Runtime::WiringError] naming the command when the two disagree
39
+ def check!(bluebook, settings)
40
+ declared = names(settings)
41
+ return if declared.empty?
42
+
43
+ known = commands_of(bluebook)
44
+ unknown = declared - known.keys
45
+ raise_unknown!(bluebook, unknown, known) unless unknown.empty?
46
+
47
+ unnamed = known.select { |name, flagged| flagged && !declared.include?(name) }.keys
48
+ raise_unnamed!(bluebook, unnamed, declared) unless unnamed.empty?
49
+ end
50
+
51
+ # @return [Hash{String => Boolean}] `Aggregate.Command` => whether it says `mints_era true`
52
+ def commands_of(bluebook)
53
+ bluebook.aggregates.flat_map do |aggregate|
54
+ aggregate.commands.map { |command| ["#{aggregate.hecks_name}.#{command.hecks_name}", command.mints_era?] }
55
+ end.to_h
56
+ end
57
+
58
+ def raise_unknown!(bluebook, unknown, known)
59
+ raise Runtime::WiringError,
60
+ "the world's mints_era names #{unknown.join(", ")}, but #{bluebook.name} declares no such command " \
61
+ "(its commands: #{known.keys.join(", ")}). A name that matches nothing would let no write through " \
62
+ "an unminted boot, so the boot refuses."
63
+ end
64
+
65
+ def raise_unnamed!(bluebook, unnamed, declared)
66
+ raise Runtime::WiringError,
67
+ "#{unnamed.join(", ")} declares `mints_era true` in #{bluebook.name}, but the world's mints_era " \
68
+ "(#{declared.join(", ")}) does not name it. Name it in the world, or remove the word from the " \
69
+ "command: the two must agree."
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -4,6 +4,7 @@ require_relative "lineage"
4
4
  require_relative "../../../../naming"
5
5
  require_relative "../../../../framework"
6
6
  require_relative "../../../../framework_bluebooks"
7
+ require_relative "../../../../module_folders"
7
8
  require_relative "../../../../runtime/registry"
8
9
 
9
10
  module Hecks
@@ -67,10 +68,10 @@ module Hecks
67
68
 
68
69
  # Reads the source text one bluebook was declared in, wherever that source lives.
69
70
  #
70
- # Matched by declared name, not position: a domain directory using
71
- # `attaches` may hold more than one file, and a framework
72
- # member or vendored bluebook is excluded from the single-file
73
- # fallback so its own real source is read, not a sibling's.
71
+ # Matched by declared name, not position, over the files the loader reads in its order
72
+ # (ModuleFolders.all): a held era freezes this text, so a domain split into module folders
73
+ # is held whole. A framework member or vendored bluebook is left out of the single-file
74
+ # fallback so its own source is read, not a sibling's.
74
75
  #
75
76
  # @param bluebook [Bluebook::Declaration] the bluebook whose source is wanted
76
77
  # @param directory [String] path of the domain's own bluebook directory
@@ -78,7 +79,7 @@ module Hecks
78
79
  # @return [String, nil] UTF-8 text of every matching file joined with `"\n"`, or nil
79
80
  def source_text_for(bluebook, directory, registry: nil)
80
81
  domain_files = Dir[File.join(directory, "*.bluebook")]
81
- own = domain_files.select { |path| declares_bluebook?(path, bluebook.name) }
82
+ own = ModuleFolders.all(directory).select { |path| declares_bluebook?(path, bluebook.name) }
82
83
  own = fallback_source_files(bluebook, directory, domain_files, registry) if own.empty?
83
84
  return if own.empty?
84
85
 
@@ -68,10 +68,14 @@ module Hecks
68
68
  paths.reject { |path| lineage.explains?(path) }
69
69
  end
70
70
 
71
- # Compares one path's held and current types, recursing into shared members.
71
+ # Compares one path's held and current types, recursing into shared members. A type is
72
+ # compared by its name: a stored shape holds every type as its string
73
+ # (`"Reference<Target>"`), a declared bluebook may hold an object that prints the same.
72
74
  # A `list_of` entity is diffed only for member drift; no per-element translation exists, so
73
75
  # only a top-level `drop` of the whole list satisfies it.
74
76
  def diff_type(path, held_type, current_type, sides, seen = [])
77
+ held_type = held_type.to_s
78
+ current_type = current_type.to_s
75
79
  return [path] if retype_drift?(held_type, current_type, sides.lineage)
76
80
  return [] if seen.include?(current_type)
77
81
 
@@ -0,0 +1,48 @@
1
+ require_relative "era_check"
2
+ require_relative "storage_shape"
3
+
4
+ module Hecks
5
+ module Runtime
6
+ # What a boot would resolve for each bluebook a registry loaded, asked of the same adapter the
7
+ # boot's era gate asks (`EraCheck`), against the database each bluebook's own world declares.
8
+ # Nothing is minted, provisioned or recorded: an era-holding adapter answers over a connection
9
+ # that can only read. A bluebook bound to an adapter that holds no eras answers `no_eras`.
10
+ module EraStatus
11
+ module_function
12
+
13
+ # @param registry [Runtime::Registry] the loaded registry, as a boot loads it
14
+ # @param directory [String] the domain's bluebook directory
15
+ # @return [Hash{String => Hash}] each bluebook's status row, by name: `status`, `held`,
16
+ # `current`, `ordinal`, `move`, `reason` and `source` (`database`, or `none` for `no_eras`)
17
+ # @raise [Runtime::WiringError] if a binding cannot be resolved, a database is unreachable, or
18
+ # a held text was altered
19
+ def rows(registry, directory)
20
+ registry.bluebooks.to_h { |name, bluebook| [name, row_for(registry, bluebook, directory)] }
21
+ end
22
+
23
+ # One bluebook's status row.
24
+ #
25
+ # @param registry [Runtime::Registry] the loaded registry
26
+ # @param bluebook [Bluebook::Declaration] the bluebook as it stands
27
+ # @param directory [String] the domain's bluebook directory
28
+ # @return [Hash] the row
29
+ def row_for(registry, bluebook, directory)
30
+ first = bluebook.aggregates.first
31
+ adapter = first && EraCheck.adapter_for(registry, bluebook.name, first)
32
+ return no_eras(bluebook, adapter || "nothing") unless adapter && EraCheck.lineage_capable?(registry, adapter)
33
+
34
+ settings = registry.binding_settings(bluebook.name, Ports::Persistence::VERB, adapter)
35
+ registry.adapter_class(adapter).era_status(registry: registry, bluebook: bluebook, settings: settings,
36
+ directory: directory).to_row
37
+ end
38
+
39
+ # @param bluebook [Bluebook::Declaration] the bluebook
40
+ # @param adapter [String] the adapter it is bound to
41
+ # @return [Hash] the row of a bluebook whose store holds no eras
42
+ def no_eras(bluebook, adapter)
43
+ { "status" => "no_eras", "held" => nil, "current" => StorageShape.mint_label(bluebook), "ordinal" => nil,
44
+ "move" => nil, "reason" => "#{bluebook.name} is bound to #{adapter}, which holds no eras", "source" => "none" }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,127 @@
1
+ require "digest"
2
+ require "json"
3
+
4
+ module Hecks
5
+ module Runtime
6
+ # A held era read from the storage shape its mint recorded, answering the bluebook questions an
7
+ # era's diff, additive rule and coverage check ask of the side they translate from: each
8
+ # aggregate's name, identity paths and attributes, and each value object's members.
9
+ #
10
+ # The shape is what an era is: its hash is the SHA-256 of the shape's canonical JSON, the same
11
+ # one `StorageShape.mint_hash` takes of a declared bluebook. Nothing here parses held text.
12
+ class ProjectedBluebook
13
+ # One attribute or value-object member, by name and type name. The name is a Symbol and the
14
+ # type name a String, as a declared bluebook answers them.
15
+ Attribute = Data.define(:name, :type, :list) do
16
+ # @return [Boolean] whether the attribute holds a list
17
+ def list? = list
18
+ end
19
+
20
+ # A value object or entity an attribute's type names, with its members.
21
+ Container = Data.define(:name, :attributes) do
22
+ # @param name [String, Symbol] a member name
23
+ # @return [Attribute, nil] the member of that name
24
+ def attribute(name) = attributes.find { |member| member.name.to_s == name.to_s }
25
+ end
26
+
27
+ # One aggregate of the held shape.
28
+ class Aggregate
29
+ attr_reader :name, :identity_paths, :attributes
30
+
31
+ # @param shape [Hash{String => Object}] one entry of the projection's `aggregates`
32
+ def initialize(shape)
33
+ @name = shape["name"]
34
+ @identity_paths = Array(shape["identity"])
35
+ @containers = {}
36
+ @attributes = Array(shape["attributes"]).map { |attribute| read(attribute) }
37
+ end
38
+
39
+ # @param name [String, Symbol] an attribute name
40
+ # @return [Attribute, nil] the attribute of that name
41
+ def attribute(name) = attributes.find { |attribute| attribute.name.to_s == name.to_s }
42
+
43
+ # @param type_name [String] a type name an attribute or member names
44
+ # @return [Container, nil] the value object or entity of that name
45
+ def value_object(type_name) = @containers[type_name]
46
+
47
+ # @return [Array] none: entities are answered as containers by `value_object`
48
+ def entities = []
49
+
50
+ private
51
+
52
+ # Reads one attribute or member, keeping the container its type expands to.
53
+ def read(attribute)
54
+ type = attribute["type"]
55
+ type = contain(type) if type.is_a?(Hash)
56
+ Attribute.new(name: attribute["name"].to_sym, type: type, list: attribute["list"] == true)
57
+ end
58
+
59
+ # Keeps the value object or entity a type expands to, and answers its name.
60
+ def contain(type)
61
+ name = type["type"]
62
+ @containers[name] ||= Container.new(name: name, attributes: Array(type["members"]).map { |member| read(member) })
63
+ name
64
+ end
65
+ end
66
+
67
+ attr_reader :projection, :name, :aggregates
68
+
69
+ # @param projection [Hash{String => Object}] a storage shape, as `StorageShape.project`
70
+ # answers it or as `hecks_eras.held_projection` stores it
71
+ def initialize(projection)
72
+ @projection = projection
73
+ @name = projection["name"]
74
+ @aggregates = Array(projection["aggregates"]).map { |shape| Aggregate.new(shape) }
75
+ end
76
+
77
+ # @param projection_or_bluebook [Hash, ProjectedBluebook, Object] a storage shape, a view, or
78
+ # a declared bluebook
79
+ # @return [ProjectedBluebook, Object] a storage shape wrapped as a view; anything else as
80
+ # given
81
+ def self.wrap(projection_or_bluebook)
82
+ projection_or_bluebook.is_a?(Hash) ? new(projection_or_bluebook) : projection_or_bluebook
83
+ end
84
+
85
+ # @param name [String, Symbol] an aggregate name
86
+ # @return [Aggregate, nil] the aggregate of that name
87
+ def aggregate(name) = aggregates.find { |aggregate| aggregate.name == name.to_s }
88
+
89
+ # @return [nil] a held shape carries no rename marker; the declared bluebook does
90
+ def formerly_known_as = nil
91
+
92
+ # @return [String] the era's hash: the SHA-256 of the shape's canonical JSON
93
+ def mint_hash = Digest::SHA256.hexdigest(JSON.generate(Canonical.shape(projection)))
94
+
95
+ # The storage shape with its keys in the order `StorageShape.project` builds them, so a shape
96
+ # read back from `jsonb`, which reorders keys, hashes as it did when it was minted.
97
+ module Canonical
98
+ module_function
99
+
100
+ # @param shape [Hash] a storage shape
101
+ # @return [Hash] the shape with its keys in canonical order
102
+ def shape(shape)
103
+ { "name" => shape["name"], "aggregates" => Array(shape["aggregates"]).map { |aggregate| aggregate(aggregate) } }
104
+ end
105
+
106
+ # @return [Hash] one aggregate's shape in canonical key order
107
+ def aggregate(aggregate)
108
+ { "name" => aggregate["name"], "identity" => aggregate["identity"],
109
+ "lifecycle_field" => aggregate["lifecycle_field"],
110
+ "attributes" => Array(aggregate["attributes"]).map { |attribute| attribute(attribute) } }
111
+ end
112
+
113
+ # @return [Hash] one attribute's shape in canonical key order
114
+ def attribute(attribute)
115
+ { "name" => attribute["name"], "list" => attribute["list"], "type" => type(attribute["type"]) }
116
+ end
117
+
118
+ # @return [String, Hash] a scalar type as given, or a container in canonical key order
119
+ def type(type)
120
+ return type unless type.is_a?(Hash)
121
+
122
+ { "type" => type["type"], "members" => Array(type["members"]).map { |member| attribute(member) } }
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end