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,1066 @@
1
+ Hecks.bluebook "Hecks" do
2
+ domain_module "Migrate" do
3
+ vision "Move a store between shapes."
4
+
5
+ aggregate "Era" do
6
+ description "One change to a domain's journal of eras, and how it ended: a store's upkeep."
7
+
8
+ acknowledges :key_by_value, "the domain's path, and Introspection declares queries only, so it holds no records and a reference would be refused on every write",
9
+ of: :domain
10
+
11
+ attribute :run, RunKey
12
+ attribute :domain, DomainPath
13
+ attribute :operation, OperationName, optional: true
14
+ attribute :winners, WinnerList, optional: true
15
+ attribute :era, Ordinal, optional: true
16
+ attribute :aggregates, AggregateList, optional: true
17
+ attribute :confirm, Switch, optional: true
18
+ attribute :capable, Switch, optional: true
19
+ attribute :held, Count, optional: true
20
+ attribute :forks, Count, optional: true
21
+ attribute :contested, Count, optional: true
22
+ attribute :bound, Count, optional: true
23
+ attribute :candidates, Count, optional: true
24
+ attribute :drifted, Switch, optional: true
25
+ attribute :loadable, Switch, optional: true
26
+ attribute :shape_kept, Switch, optional: true
27
+ attribute :report, Report, optional: true
28
+ attribute :refusal, Report, optional: true
29
+ identified_by :run
30
+
31
+ value_object "RunKey" do
32
+ attribute :value, String, matches: :present
33
+
34
+ invariant("a change is named") { !value.to_s.empty? }
35
+ end
36
+
37
+ # The domain whose journal is changed: its directory.
38
+ value_object "DomainPath" do
39
+ attribute :value, String, matches: :not_empty
40
+ end
41
+
42
+ value_object "OperationName" do
43
+ attribute :value, String,
44
+ pattern: '^(hold_first|rename_domain|merge_tail|reattest|backfill_projections|compact|compact_heki|write_translation|reconcile)$'
45
+ end
46
+
47
+ # `id:old,id:new`: which world's record wins for each id both worlds touched since the cut.
48
+ value_object "WinnerList" do
49
+ attribute :value, String, pattern: '^[^ \t\n\r,]+:(old|new)(,[^ \t\n\r,]+:(old|new))*$'
50
+ end
51
+
52
+ value_object "Ordinal" do
53
+ attribute :value, Integer
54
+
55
+ invariant("an era is counted from one") { value > 0 }
56
+ end
57
+
58
+ # Aggregate names, comma separated; every aggregate that keeps a journal when absent.
59
+ value_object "AggregateList" do
60
+ attribute :value, String, matches: :not_empty
61
+ end
62
+
63
+ value_object "Switch" do
64
+ attribute :value, Boolean
65
+ end
66
+
67
+ value_object "Count" do
68
+ attribute :value, Integer
69
+ end
70
+
71
+ # The rehearsal verdict a mint was asked with: the one the caller read, compared with the decision.
72
+ value_object "MintVerdict" do
73
+ attribute :value, String, one_of: ["would_mint", "no_change", "would_refuse", "needs_edge",
74
+ "cannot_boot", "empty_copy"]
75
+ end
76
+
77
+ # The ledger watermark a mint was asked at: the newest held era's ordinal.
78
+ value_object "Watermark" do
79
+ attribute :value, Integer
80
+ end
81
+
82
+ value_object "Report" do
83
+ attribute :value, String
84
+ end
85
+
86
+ lifecycle :status, default: "requested" do
87
+ mark :failure, "refused"
88
+ transition "Permit" => "admitted", from: "requested"
89
+ transition "Settle" => "settled", from: "admitted"
90
+ transition "Abandon" => "refused", from: %w[requested admitted]
91
+ mark :terminal, "refused", "settled"
92
+ end
93
+
94
+ # The seven requests. Each records what was asked and names its operation; the journal store
95
+ # then examines the domain and reports facts (`EraExamined`), `Permit` holds the rules that need
96
+ # those facts, and only an admitted change is made (`EraChanged`). A change that changes
97
+ # something needs an explicit `--confirm`.
98
+ command "HoldFirst" do
99
+ role "Operator"
100
+ goal "Hold the first era of a domain that holds none, as its first boot would"
101
+
102
+ attribute :domain, DomainPath, sets: true
103
+ attribute :run, RunKey, sets: true
104
+ attribute :confirm, Switch, optional: true, sets: true
105
+
106
+ given("holding the first era is confirmed") { confirm.value == true }
107
+
108
+ sets :operation, to: "hold_first"
109
+
110
+ emits FirstEraRequested
111
+ end
112
+
113
+ # Moves the history a domain held under its `formerly_known_as` name to its current name, in one
114
+ # transaction: the eras, their texts and attestations, the journal with its sequence and
115
+ # partitions. Nothing is copied, so the old name holds nothing after it. A boot under the new
116
+ # name before this refuses by name; it never starts a fresh history beside the old.
117
+ command "RenameDomain" do
118
+ role "Operator"
119
+ goal "Move a renamed domain's held eras and journal from its former name to its current name"
120
+
121
+ attribute :domain, DomainPath, sets: true
122
+ attribute :run, RunKey, sets: true
123
+ attribute :confirm, Switch, optional: true, sets: true
124
+
125
+ given("the rename is confirmed") { confirm.value == true }
126
+
127
+ sets :operation, to: "rename_domain"
128
+
129
+ emits DomainRenameRequested
130
+ end
131
+
132
+ command "MergeTail" do
133
+ role "Operator"
134
+ goal "Interleave the old world's writes since the cut into the live head, by their ordinals"
135
+
136
+ attribute :domain, DomainPath, sets: true
137
+ attribute :run, RunKey, sets: true
138
+ attribute :winners, WinnerList, optional: true, sets: true
139
+ attribute :confirm, Switch, optional: true, sets: true
140
+
141
+ given("the merge is confirmed") { confirm.value == true }
142
+
143
+ sets :operation, to: "merge_tail"
144
+
145
+ emits TailMergeRequested
146
+ end
147
+
148
+ command "Reattest" do
149
+ role "Operator"
150
+ goal "Freeze an era's held text as it now stands, after a person has read it"
151
+
152
+ attribute :domain, DomainPath, sets: true
153
+ attribute :era, Ordinal, sets: true
154
+ attribute :run, RunKey, sets: true
155
+ attribute :confirm, Switch, optional: true, sets: true
156
+
157
+ given("the text is accepted as the era's own") { confirm.value == true }
158
+
159
+ sets :operation, to: "reattest"
160
+
161
+ emits ReattestRequested
162
+ end
163
+
164
+ command "BackfillProjections" do
165
+ role "Operator"
166
+ goal "Store the shape every held era froze with, for the eras that predate it"
167
+
168
+ attribute :domain, DomainPath, sets: true
169
+ attribute :run, RunKey, sets: true
170
+
171
+ sets :operation, to: "backfill_projections"
172
+
173
+ emits BackfillRequested
174
+ end
175
+
176
+ command "Compact" do
177
+ role "Operator"
178
+ goal "Delete the journal entries a Postgres or Sqlite aggregate has already projected"
179
+
180
+ attribute :domain, DomainPath, sets: true
181
+ attribute :aggregates, AggregateList, optional: true, sets: true
182
+ attribute :run, RunKey, sets: true
183
+ attribute :confirm, Switch, optional: true, sets: true
184
+
185
+ given("the compaction is confirmed") { confirm.value == true }
186
+
187
+ sets :operation, to: "compact"
188
+
189
+ emits CompactionRequested
190
+ end
191
+
192
+ command "CompactHeki" do
193
+ role "Operator"
194
+ goal "Empty a Heki aggregate's journal, keeping the snapshot"
195
+
196
+ attribute :domain, DomainPath, sets: true
197
+ attribute :aggregates, AggregateList, optional: true, sets: true
198
+ attribute :run, RunKey, sets: true
199
+ attribute :confirm, Switch, optional: true, sets: true
200
+
201
+ given("the compaction is confirmed") { confirm.value == true }
202
+
203
+ sets :operation, to: "compact_heki"
204
+
205
+ emits HekiCompactionRequested
206
+ end
207
+
208
+ # Writes the one edge that leads the latest held era to the current shape, composed from the
209
+ # chain of edges between them, and deletes the intermediate edges only that chain used. An
210
+ # audit that refuses the written edge puts the translations directory back as it was.
211
+ command "WriteTranslation" do
212
+ role "Operator"
213
+ goal "Write the one translation edge that leads the latest held era to the current shape"
214
+
215
+ attribute :domain, DomainPath, sets: true
216
+ attribute :run, RunKey, sets: true
217
+ attribute :confirm, Switch, optional: true, sets: true
218
+
219
+ given("the edge is confirmed") { confirm.value == true }
220
+
221
+ sets :operation, to: "write_translation"
222
+
223
+ emits TranslationRequested
224
+ end
225
+
226
+ # Writes, for every domain of the project, the one edge that leads its latest held era to its
227
+ # current shape, deletes the edges that edge supersedes, and audits what it wrote. Any refused
228
+ # domain writes nothing. The dry run is `ReconcilePlan`: this command refuses without confirm.
229
+ command "Reconcile" do
230
+ role "Operator"
231
+ goal "Write the translation edges that lead every domain's latest held era to its current shape"
232
+
233
+ attribute :domain, DomainPath, optional: true, sets: true
234
+ attribute :run, RunKey, sets: true
235
+ attribute :confirm, Switch, optional: true, sets: true
236
+
237
+ given("the reconciliation is confirmed") { confirm.value == true }
238
+
239
+ sets :operation, to: "reconcile"
240
+
241
+ emits ReconcileRequested
242
+ end
243
+
244
+ # Mints the Hecks domain's next era when its shape moved, through the mint transaction the
245
+ # QualityControl mint uses. The journal store decides again at the live watermark: only a
246
+ # `would_mint` decision mints, and a shape that did not move answers `no_change` and mints nothing.
247
+ # The rehearsal verdict and watermark are optional, since the push train asks with neither.
248
+ command "MintHeld" do
249
+ role "Operator"
250
+ goal "Mint the Hecks domain's next era when its shape moved, before the push train writes"
251
+ attribute :run, RunKey, sets: true
252
+ attribute :rehearsal_verdict, MintVerdict, optional: true
253
+ attribute :watermark, Watermark, optional: true
254
+ attribute :confirm, Switch, optional: true, sets: true
255
+
256
+ given("minting the era is confirmed") { confirm.value == true }
257
+
258
+ emits HeldMintRequested
259
+ end
260
+
261
+ # The facts the journal store reported, held against the change that was asked for.
262
+ command "Permit" do
263
+ role "System"
264
+ goal "Let a change through only when what was found in the journal allows it"
265
+
266
+ reference_to Era
267
+ attribute :capable, Switch, sets: true
268
+ attribute :held, Count, sets: true
269
+ attribute :forks, Count, sets: true
270
+ attribute :contested, Count, sets: true
271
+ attribute :bound, Count, sets: true
272
+ attribute :candidates, Count, sets: true
273
+ attribute :drifted, Switch, sets: true
274
+ attribute :loadable, Switch, sets: true
275
+ attribute :shape_kept, Switch, sets: true
276
+ attribute :operation, OperationName, sets: true
277
+
278
+ given("the store keeps eras") do
279
+ capable.value || operation.value == "compact" || operation.value == "compact_heki"
280
+ end
281
+ given("no era is held yet") { operation.value != "hold_first" || held.value == 0 }
282
+ given("the former name holds eras to move, and the current name holds none") do
283
+ operation.value != "rename_domain" || held.value > 0
284
+ end
285
+ given("an era beyond the first stands before a tail is merged") do
286
+ operation.value != "merge_tail" || held.value > 1
287
+ end
288
+ given("exactly one edge leaves each era") { operation.value != "merge_tail" || forks.value == 0 }
289
+ given("every record both worlds touched has a named winner") do
290
+ operation.value != "merge_tail" || contested.value == 0
291
+ end
292
+ given("an aggregate matches") do
293
+ (operation.value != "compact" && operation.value != "compact_heki") || candidates.value > 0
294
+ end
295
+ given("no projection reads the journal that would be emptied") do
296
+ (operation.value != "compact" && operation.value != "compact_heki") || bound.value == 0
297
+ end
298
+ given("the held text no longer matches its digest: there is nothing to re-attest") do
299
+ operation.value != "reattest" || drifted.value
300
+ end
301
+ given("the domain holds an era to lead from") { operation.value != "write_translation" || held.value > 0 }
302
+ given("the edited text loads as a bluebook: restore a loadable text") do
303
+ operation.value != "reattest" || loadable.value
304
+ end
305
+ given("the edit kept the era's shape, not just its text: restore a text with the original shape") do
306
+ operation.value != "reattest" || shape_kept.value
307
+ end
308
+
309
+
310
+ emits EraPermitted
311
+ end
312
+
313
+ command "Settle" do
314
+ role "System"
315
+ goal "Record that the admitted change was made, and what it did"
316
+
317
+ reference_to Era
318
+ attribute :report, Report, sets: true
319
+
320
+
321
+ emits EraSettled
322
+ end
323
+
324
+ command "Abandon" do
325
+ role "System"
326
+ goal "Record that the change was refused, or could not be made, and why"
327
+
328
+ reference_to Era
329
+ attribute :refusal, Report, sets: true
330
+
331
+
332
+ emits EraAbandoned
333
+ end
334
+
335
+ query "Settlement" do
336
+ description "What one change did: its status, and the report or the reason it was refused."
337
+ attribute :run, RunKey
338
+ where(run: :run)
339
+ order_by :run
340
+ end
341
+
342
+ query "Abandoned" do
343
+ description "Every change that was refused or could not be made."
344
+ where(status: "refused")
345
+ order_by :run
346
+ end
347
+
348
+ # An answer that is one document of text, exactly as the tool that produced it wrote it.
349
+ value_object "Document" do
350
+ attribute :text, String
351
+ end
352
+
353
+ # The reads that used to write. None holds an era or names one: a domain that holds no era
354
+ # answers "no era held yet", and `hold_first` is the only thing that holds the first.
355
+ query "ScaffoldTranslation" do
356
+ description "The edge file that would lead the latest held era to the current shape."
357
+ attribute :domain, DomainPath
358
+ returns Document
359
+ end
360
+
361
+ query "AuditTranslation" do
362
+ description "The audit of the edge that leads the latest held era to the current shape."
363
+ attribute :domain, DomainPath
364
+ returns Document
365
+ end
366
+
367
+ # The edge `write_translation` would write and the edges it would delete, written nowhere.
368
+ query "ComposeTranslation" do
369
+ description "The one edge write_translation would write, and the stale edges it would delete."
370
+ attribute :domain, DomainPath
371
+ returns Document
372
+ end
373
+
374
+ # The dry run of `Reconcile`: each domain's held era, current shape, edge it would write, edges it
375
+ # would delete, and the verdict, written nowhere.
376
+ query "ReconcilePlan" do
377
+ description "The dry run of Era.Reconcile: per domain, the held era, the current shape, the edge " \
378
+ "it would write, the edges it would delete, and the verdict."
379
+ attribute :domain, DomainPath, optional: true
380
+ returns Document
381
+ end
382
+
383
+ query "Attestation" do
384
+ description "An era's held text as it now stands, and whether it still matches its digest."
385
+ attribute :domain, DomainPath
386
+ attribute :era, Ordinal
387
+ returns Document
388
+ end
389
+
390
+ query "Compaction" do
391
+ description "What compacting the domain's journals would delete, without deleting it."
392
+ attribute :domain, DomainPath
393
+ attribute :aggregates, AggregateList, optional: true
394
+ returns Document
395
+ end
396
+
397
+ # The boot status of each bluebook under a domain directory, resolved as its boot resolves it:
398
+ # from the database its own world declares, or, for a bluebook bound to a store that holds no
399
+ # eras, from the committed ledger and its edges. Each row names its source. Nothing is minted
400
+ # or written.
401
+ query "BootStatus" do
402
+ description "The boot status of each bluebook under a domain directory: current, behind by a recorded " \
403
+ "implicit move, superseded, or unminted, with the held and current labels and the reason; " \
404
+ "read from its own database when it declares one, else from the committed ledger."
405
+ attribute :domain, DomainPath
406
+ returns Document
407
+ end
408
+
409
+ # What a boot would resolve for each bluebook under a domain directory, read from the database
410
+ # its own world declares by the resolution the boot records, over a connection that only reads.
411
+ query "BootResolution" do
412
+ description "What a boot would resolve for each bluebook under a domain directory, from its own " \
413
+ "database: status, held label, current label, ordinal and reason. Writes nothing."
414
+ attribute :domain, DomainPath
415
+ returns Document
416
+ end
417
+
418
+ # How each SQLite database a domain's worlds name stands against the aggregates that map onto
419
+ # it, opened read-only so the adapter's own healing never runs.
420
+ query "SqliteStatus" do
421
+ description "The SQLite databases a domain's worlds name, read-only: per aggregate table the columns " \
422
+ "the aggregate declares and the table lacks (added on the next open), the columns it keeps " \
423
+ "that the aggregate no longer declares, and the tables no aggregate maps to."
424
+ attribute :domain, DomainPath
425
+ returns Document
426
+ end
427
+
428
+ # Whether the events a domain's store recorded were seen and answered: per event, each policy
429
+ # that listens to it (resolved from the bluebooks) and the outcome the store's outbox holds for
430
+ # the pair. Opens each store read-only and never boots the domain.
431
+ query "EventTrace" do
432
+ description "Per recorded event: the policies that listen to it and what became of each delivery " \
433
+ "(delivered, refused with its reason, pending, claimed, failed, or no record), the events " \
434
+ "nobody listens to, and the policies whose event never occurred. Reads only; Memory keeps no log."
435
+ attribute :domain, DomainPath
436
+ attribute :event, String, optional: true
437
+ attribute :run, String, optional: true
438
+ attribute :last, Integer, optional: true
439
+ attribute :database, String, optional: true
440
+ returns Document
441
+ end
442
+
443
+ # Whether each era's stored hash is the hash of its stored projection.
444
+ query "ProjectionAudit" do
445
+ description "Every era of each bluebook under a domain directory whose stored hash is not the hash of " \
446
+ "its stored projection: domain, ordinal, stored hash and recomputed hash. Writes nothing."
447
+ attribute :domain, DomainPath
448
+ returns Document
449
+ end
450
+
451
+ # The preflight of a mint: every guard the mint runs, answered from the live store without copying it.
452
+ # Opens the store read-only and never boots the domain; the full rehearsal still runs once before the mint.
453
+ query "MintPlan" do
454
+ description "Runs every guard a mint runs against the live store, read-only and in seconds: the era resolution and decision, " \
455
+ "the edge checks, the coverage check, the translation audit (Ruby only; parity needs the full rehearsal), " \
456
+ "the watermark rule, the world's flags and markers, and the freshness of a rehearsal ref when one is passed. " \
457
+ "Names one bluebook of the directory, the first by default. Answers each guard's status, whether the mint would go ahead, and the exact mint command to run."
458
+ attribute :domain, DomainPath
459
+ attribute :bluebook, String, optional: true
460
+ attribute :rehearsal_ref, String, optional: true
461
+ attribute :rehearsal_watermark, Integer, optional: true
462
+ attribute :rehearsal_verdict, String, optional: true
463
+ returns Document
464
+ end
465
+ end
466
+
467
+ policy "ExamineWhenFirstEraRequested" do
468
+ on "Era.FirstEraRequested"
469
+ ask :examine, with: { run: :run }
470
+ end
471
+
472
+ policy "ExamineWhenDomainRenameRequested" do
473
+ on "Era.DomainRenameRequested"
474
+ ask :examine, with: { run: :run }
475
+ end
476
+
477
+ policy "ExamineWhenTailMergeRequested" do
478
+ on "Era.TailMergeRequested"
479
+ ask :examine, with: { run: :run }
480
+ end
481
+
482
+ policy "ExamineWhenReattestRequested" do
483
+ on "Era.ReattestRequested"
484
+ ask :examine, with: { run: :run }
485
+ end
486
+
487
+ policy "ExamineWhenBackfillRequested" do
488
+ on "Era.BackfillRequested"
489
+ ask :examine, with: { run: :run }
490
+ end
491
+
492
+ policy "ExamineWhenCompactionRequested" do
493
+ on "Era.CompactionRequested"
494
+ ask :examine, with: { run: :run }
495
+ end
496
+
497
+ policy "ExamineWhenHekiCompactionRequested" do
498
+ on "Era.HekiCompactionRequested"
499
+ ask :examine, with: { run: :run }
500
+ end
501
+
502
+ policy "ExamineWhenTranslationRequested" do
503
+ on "Era.TranslationRequested"
504
+ ask :examine, with: { run: :run }
505
+ end
506
+
507
+ policy "ExamineWhenReconcileRequested" do
508
+ on "Era.ReconcileRequested"
509
+ ask :examine, with: { run: :run }
510
+ end
511
+
512
+ # The held mint is answered by the journal store: `Minted` when the shape moved and the mint ran, or
513
+ # when it did not move (`no_change`); `MintRefused` otherwise, with the reason named.
514
+ policy "MintWhenHeldRequested" do
515
+ on "Era.HeldMintRequested"
516
+ ask :mint, with: { run: :run }
517
+ end
518
+
519
+ policy "PermitWhenExamined" do
520
+ on "Era.EraExamined"
521
+ trigger Era::Permit, with: {
522
+ capable: :capable, held: :held, forks: :forks, contested: :contested,
523
+ bound: :bound, candidates: :candidates,
524
+ drifted: :drifted, loadable: :loadable, shape_kept: :shape_kept, operation: :operation
525
+ }
526
+ end
527
+
528
+ # `Permit` refuses when a rule is unmet and emits nothing, so this reaction is its complement:
529
+ # it holds the same rules negated, so an examined change that is not let through is abandoned
530
+ # rather than left `requested`.
531
+ policy "AbandonWhenNotPermitted" do
532
+ on "Era.EraExamined"
533
+ where do
534
+ (!capable.value && operation.value != "compact" && operation.value != "compact_heki") ||
535
+ (operation.value == "hold_first" && held.value != 0) ||
536
+ (operation.value == "rename_domain" && held.value == 0) ||
537
+ (operation.value == "merge_tail" && (held.value <= 1 || forks.value != 0 || contested.value != 0)) ||
538
+ ((operation.value == "compact" || operation.value == "compact_heki") &&
539
+ (candidates.value <= 0 || bound.value != 0)) ||
540
+ (operation.value == "reattest" && (!drifted.value || !loadable.value || !shape_kept.value)) ||
541
+ (operation.value == "write_translation" && held.value == 0)
542
+ end
543
+ trigger Era::Abandon, with: { refusal: "the journal's facts do not admit this change" }
544
+ end
545
+
546
+ # A compaction waits for its seal (ledger.bluebook); every other change is applied at once.
547
+ policy "ChangeWhenPermitted" do
548
+ on "Era.EraPermitted"
549
+ where do
550
+ operation.value != "compact" && operation.value != "compact_heki"
551
+ end
552
+ ask :apply, with: { run: :run }
553
+ end
554
+
555
+ policy "RecordTheChange" do
556
+ on "Era.EraChanged"
557
+ trigger Era::Settle, with: { report: :report }
558
+ end
559
+
560
+ policy "RecordTheRefusedChange" do
561
+ on "Era.EraRefused"
562
+ trigger Era::Abandon, with: { refusal: :refusal }
563
+ end
564
+
565
+ # Ledger: a journal that proves it was not rewritten. A seal records the head a journal chain has,
566
+ # kept beside the journal itself; an Audit recomputes the chain from the seals and compares. Compaction
567
+ # is the one sanctioned way rows leave a journal, so it seals first: the capture is one ask on the Era
568
+ # being changed (the reaction depth is bounded, so the seal cannot be a chain of its own), and a
569
+ # compaction whose head cannot be captured is abandoned, not applied.
570
+
571
+ aggregate "Seal" do
572
+ description "The head a domain's journal chain had when the rows before it were compacted away."
573
+
574
+ attribute :run, SealKey
575
+ attribute :domain, Domain
576
+ attribute :through, Ordinal
577
+ attribute :head, ChainDigest
578
+ attribute :previous, ChainDigest
579
+ identified_by :run
580
+
581
+ value_object "SealKey" do
582
+ attribute :value, String, matches: :present
583
+
584
+ invariant("a seal is named") { !value.to_s.empty? }
585
+ end
586
+
587
+ # The domain whose journal is sealed: its directory.
588
+ value_object "Domain" do
589
+ attribute :value, String, matches: :not_empty
590
+ end
591
+
592
+ # The last journal ordinal the seal covers.
593
+ value_object "Ordinal" do
594
+ attribute :value, Integer
595
+
596
+ invariant("a seal covers at least one row") { value > 0 }
597
+ end
598
+
599
+ # A SHA-256 digest, lowercase hexadecimal.
600
+ value_object "ChainDigest" do
601
+ attribute :value, String, pattern: '^[0-9a-f]{64}$'
602
+ end
603
+
604
+ # `previous` is the head of the seal before this one, so seals chain too; the first seal
605
+ # of a domain carries the genesis digest, sixty-four zeros.
606
+ command "Record" do
607
+ role "System"
608
+ goal "Keep the head the chain had, and the seal it followed"
609
+
610
+ attribute :domain, Domain, sets: true
611
+ attribute :run, SealKey, sets: true
612
+ attribute :through, Ordinal, sets: true
613
+ attribute :head, ChainDigest, sets: true
614
+ attribute :previous, ChainDigest, sets: true
615
+
616
+
617
+ emits SealRecorded
618
+ end
619
+
620
+ query "Latest" do
621
+ description "The newest seal a domain holds."
622
+ attribute :domain, Domain
623
+ where(domain: :domain)
624
+ order_by :through
625
+ end
626
+
627
+ end
628
+
629
+ # Rehearsal: operating a domain, in the Operations module (ADR 0096). Whether a domain at a pin
630
+ # would mint its next era against a copy of its real data, and what the mint would refuse.
631
+ #
632
+ # A rehearsal is a run like the Codebase `*Run`s: it is requested, the outside is asked, and the
633
+ # facts it brought back are judged by the givens and reactions below. It differs from them in
634
+ # two ways. It acts on a client's domain, not on this checkout, so it needs no hecks checkout
635
+ # and sits with Custodian, not Codebase. And it keeps nothing: the aggregate is bound to Memory
636
+ # in hecks.hecksagon, and what it found is its report, returned to the caller.
637
+ #
638
+ # Where the data it reads comes from is the subject's own `.world` (`rehearsed_by`), never an
639
+ # argument. The RehearsalStore port prepares that copy, loads the domain against it, runs the
640
+ # mint's audit over it without writing an era, and drops it, so the copy never outlives the run
641
+ # whichever way the chain of reactions ends.
642
+
643
+ aggregate "RehearsalRun" do
644
+ description "One rehearsal of a domain's next era against a copy of its data: what a mint would do, and what it would refuse."
645
+
646
+ acknowledges :key_by_value, "the domain's path, and Introspection declares queries only, so it holds no records and a reference would be refused on every write",
647
+ of: :domain
648
+
649
+ attribute :run, RunKey
650
+ attribute :domain, DomainPath
651
+ attribute :pin, Pin, optional: true
652
+ attribute :host_version, HostVersion, optional: true
653
+ attribute :store, StoreKind, optional: true
654
+ attribute :mode, StoreMode, optional: true
655
+ attribute :environment_loaded, EnvironmentLoaded, optional: true
656
+ attribute :schema_used, SchemaRead, optional: true
657
+ attribute :eras_held, Count, optional: true
658
+ attribute :journal_entries, Count, optional: true
659
+ attribute :head_rows, Count, optional: true
660
+ attribute :census, list_of(HeldCount), optional: true
661
+ attribute :copy_empty, Switch, optional: true
662
+ attribute :copy_note, Report, optional: true
663
+ attribute :booted, Switch, optional: true
664
+ attribute :before, ShapeLabel, optional: true
665
+ attribute :after, ShapeLabel, optional: true
666
+ attribute :minting, Minting, optional: true
667
+ attribute :edge_present, Switch, optional: true
668
+ attribute :refused_rows, list_of(RefusedRow), optional: true
669
+ attribute :refusal_total, Count, optional: true
670
+ attribute :audited, Switch, optional: true
671
+ attribute :rows_examined, Count, optional: true
672
+ attribute :rust_rows_examined, Count, optional: true
673
+ attribute :aggregates_examined, Count, optional: true
674
+ attribute :reason, Report, optional: true
675
+ attribute :parity, Parity, optional: true
676
+ attribute :unchecked, list_of(Limit), optional: true
677
+ attribute :verdict, Verdict, optional: true
678
+ attribute :released, Switch, optional: true
679
+ attribute :kept, Report, optional: true
680
+ attribute :boot_error, Report, optional: true
681
+ attribute :refusal, Report, optional: true
682
+ identified_by :run
683
+
684
+ value_object "RunKey" do
685
+ attribute :value, String, matches: :present
686
+
687
+ invariant("a rehearsal is named") { !value.to_s.empty? }
688
+ end
689
+
690
+ # The domain's directory: where its bluebooks and its `.world` stand.
691
+ value_object "DomainPath" do
692
+ attribute :value, String, matches: :not_empty
693
+ end
694
+
695
+ # The Hecks the rehearsal must run on: a release (`3.9.0`) or a commit, whole or a prefix.
696
+ value_object "Pin" do
697
+ attribute :value, String, pattern: '^[0-9a-f]{7,40}$|^[0-9]+[.][0-9]+[.][0-9]+'
698
+ end
699
+
700
+ value_object "HostVersion" do
701
+ attribute :value, String, matches: :present
702
+ end
703
+
704
+ # Which strategy the subject's world named for the copy of its data.
705
+ value_object "StoreKind" do
706
+ attribute :value, String, one_of: ["memory", "postgres"]
707
+
708
+ invariant("a store is one the language names") { ["memory", "postgres"].include?(value) }
709
+ end
710
+
711
+ # What the copy holds: nothing, a restored dump, or a copy somebody else made, read as it is.
712
+ value_object "StoreMode" do
713
+ attribute :value, String, one_of: ["empty", "dump", "readonly_copy"]
714
+
715
+ invariant("a mode is empty, dump or readonly_copy") { ["empty", "dump", "readonly_copy"].include?(value) }
716
+ end
717
+
718
+ # The environment overlay the subject was loaded under and where that was decided: `world`
719
+ # (its `rehearsed_by` named one), `HECKS_PROJECT_ENVIRONMENT`, `default` (production, because
720
+ # its overlay exists, as the host build does) or `none`. A domain's binds are usually declared
721
+ # in that overlay, so a rehearsal that loaded another one rehearsed another domain.
722
+ value_object "EnvironmentLoaded" do
723
+ attribute :name, String
724
+ attribute :source, String, pattern: '^(world|HECKS_PROJECT_ENVIRONMENT|default|none)$'
725
+ attribute :file, String
726
+ end
727
+
728
+ # The Postgres schema the copy was read in, where that was decided (`world`, `HECKS_SCHEMA`,
729
+ # `derived` from the domain's name, `default` public, or `memory` for a document) and whether
730
+ # the copy has it.
731
+ value_object "SchemaRead" do
732
+ attribute :name, String
733
+ attribute :source, String, pattern: '^(world|HECKS_SCHEMA|derived|default|memory)$'
734
+ attribute :present, Boolean
735
+ end
736
+
737
+ # One aggregate's rows in the copy: what its head table holds and the records its journal's
738
+ # latest entries hold. The audit reads the journal, so a difference is shown, not refused.
739
+ value_object "HeldCount" do
740
+ attribute :aggregate, String
741
+ attribute :head, Integer
742
+ attribute :journal, Integer
743
+ end
744
+
745
+ value_object "Switch" do
746
+ attribute :value, Boolean
747
+ end
748
+
749
+ value_object "Count" do
750
+ attribute :value, Integer
751
+
752
+ invariant("a count is not negative") { value >= 0 }
753
+ end
754
+
755
+ # The first six hex digits of a storage shape's digest, or `none` when no era is held.
756
+ value_object "ShapeLabel" do
757
+ attribute :value, String, pattern: '^[0-9a-f]{6}$|^none$'
758
+ end
759
+
760
+ # Which era a mint would hold: none (the shape stands), the first, or the next.
761
+ value_object "Minting" do
762
+ attribute :value, String, one_of: ["none", "first", "next"]
763
+
764
+ invariant("a mint is none, first or next") { ["none", "first", "next"].include?(value) }
765
+ end
766
+
767
+ # One stored record the mint's audit would refuse, named `Aggregate#id`, with the rule that
768
+ # refused it (a value the new types or invariants refuse, a state the lifecycle never reaches,
769
+ # a reference the edge cannot carry) and the audit's own wording.
770
+ value_object "RefusedRow" do
771
+ attribute :aggregate, String
772
+ attribute :id, String
773
+ attribute :rule, String, pattern: '^(value|lifecycle|reference)$'
774
+ attribute :wording, String
775
+ end
776
+
777
+ # How the other engine's audit stood: not run, in agreement with this one, or not.
778
+ value_object "Parity" do
779
+ attribute :engine, String
780
+ attribute :status, String, pattern: '^(not_run|agree|differ)$'
781
+ attribute :note, String
782
+ end
783
+
784
+ # One thing a rehearsal did not check, and why. A rehearsal states its limits.
785
+ value_object "Limit" do
786
+ attribute :what, String
787
+ attribute :why, String
788
+ end
789
+
790
+ # The five things a rehearsal can conclude. A would_mint of `minting: none` says the shape
791
+ # stands and nothing would be minted at all. `empty_copy` says the copy held no row of the
792
+ # domain, so nothing was rehearsed and no answer about the data is given.
793
+ value_object "Verdict" do
794
+ attribute :value, String, one_of: ["would_mint", "would_refuse", "needs_edge", "cannot_boot", "empty_copy"]
795
+
796
+ invariant("a verdict is one the rehearsal names") do
797
+ ["would_mint", "would_refuse", "needs_edge", "cannot_boot", "empty_copy"].include?(value)
798
+ end
799
+ end
800
+
801
+ value_object "Report" do
802
+ attribute :value, String
803
+ end
804
+
805
+ # Only the first rows are held, so a domain with a million stale rows is a report, not a
806
+ # flood; the total says how many there were.
807
+ invariant("no more than fifty refused rows are held") { refused_rows.unset? || refused_rows.size <= 50 }
808
+ invariant("the total counts at least the rows held") do
809
+ refused_rows.unset? || refusal_total.unset? || refusal_total.value >= refused_rows.size
810
+ end
811
+ invariant("a rehearsal that would mint holds no refused row") do
812
+ verdict.unset? || verdict.value != "would_mint" || refusal_total.unset? || refusal_total.value == 0
813
+ end
814
+ invariant("only a domain that booted would mint") do
815
+ verdict.unset? || verdict.value != "would_mint" || booted.unset? || booted.value
816
+ end
817
+ invariant("a copy that holds nothing is never judged to mint") do
818
+ verdict.unset? || verdict.value != "would_mint" || copy_empty.unset? || !copy_empty.value
819
+ end
820
+ invariant("an empty_copy verdict is given for a copy that holds nothing") do
821
+ verdict.unset? || verdict.value != "empty_copy" || (!copy_empty.unset? && copy_empty.value)
822
+ end
823
+ invariant("only a mint of the next era audits stored rows") do
824
+ audited.unset? || !audited.value || minting.unset? || minting.value == "next"
825
+ end
826
+ invariant("a mint of the next era that would go through states how many rows were examined") do
827
+ verdict.unset? || verdict.value != "would_mint" || minting.unset? || minting.value != "next" || !rows_examined.unset?
828
+ end
829
+ invariant("a clean verdict that examined no row says so in what it did not check") do
830
+ verdict.unset? || verdict.value != "would_mint" || audited.unset? || audited.value ||
831
+ (!unchecked.unset? && unchecked.any? { |limit| limit.what == "the stored rows" })
832
+ end
833
+
834
+ # `requested` is the rehearsal and its store being prepared; `booted` the domain loaded and
835
+ # its shape read; `audited` the mint's audit run over the data. `judged` is a rehearsal whose
836
+ # answer is that the mint would go through, `withheld` one whose answer is that it would not
837
+ # (the verdict says which way), `refused` one that was never run because the request or the
838
+ # store was not admitted, and `failed` one that broke after it began.
839
+ lifecycle :status, default: "requested" do
840
+ mark :failure, "withheld", "refused", "failed"
841
+ transition "Boot" => "booted", from: "requested"
842
+ transition "Audit" => "audited", from: "booted"
843
+ transition "Judge" => "judged", from: "audited"
844
+ transition "Withhold" => "withheld", from: %w[requested booted audited]
845
+ transition "Refuse" => "refused", from: "requested"
846
+ transition "Fail" => "failed", from: %w[requested booted audited]
847
+ mark :terminal, "failed", "judged", "refused", "withheld"
848
+ end
849
+
850
+ command "Request" do
851
+ role "Operator"
852
+ goal "Rehearse a domain's next era against the copy of its data its world names, say whether a mint would go through, and print the whole outcome"
853
+
854
+ attribute :run, RunKey, sets: true
855
+ attribute :domain, DomainPath, sets: true
856
+ attribute :pin, Pin, optional: true, sets: true
857
+
858
+
859
+ emits RehearsalRequested
860
+ end
861
+
862
+ # What the subject reported once it was loaded against the prepared copy.
863
+ command "Boot" do
864
+ role "System"
865
+ goal "Record that the domain loaded, the shape it stands at and the era a mint would hold"
866
+
867
+ reference_to RehearsalRun
868
+ attribute :booted, Switch, sets: true
869
+ attribute :host_version, HostVersion, sets: true
870
+ attribute :store, StoreKind, sets: true
871
+ attribute :mode, StoreMode, sets: true
872
+ attribute :before, ShapeLabel, sets: true
873
+ attribute :after, ShapeLabel, sets: true
874
+ attribute :minting, Minting, sets: true
875
+ attribute :environment_loaded, EnvironmentLoaded, sets: true
876
+ attribute :schema_used, SchemaRead, sets: true
877
+ attribute :eras_held, Count, sets: true
878
+ attribute :journal_entries, Count, sets: true
879
+ attribute :head_rows, Count, sets: true
880
+ attribute :census, list_of(HeldCount), sets: true
881
+ attribute :copy_empty, Switch, sets: true
882
+ attribute :copy_note, Report, sets: true
883
+ attribute :released, Switch, optional: true, sets: true
884
+ attribute :kept, Report, optional: true, sets: true
885
+
886
+ given("the domain loaded") { booted.value }
887
+
888
+
889
+ emits RehearsalBooted
890
+ end
891
+
892
+ # The mint's own three layers and its edge and coverage rules, run over the copy.
893
+ command "Audit" do
894
+ role "System"
895
+ goal "Record whether an edge leads to the shape, and every row the mint's audit would refuse"
896
+
897
+ reference_to RehearsalRun
898
+ attribute :minting, Minting, sets: true
899
+ attribute :edge_present, Switch, sets: true
900
+ attribute :refused_rows, list_of(RefusedRow), optional: true, sets: true
901
+ attribute :refusal_total, Count, sets: true
902
+ attribute :audited, Switch, sets: true
903
+ attribute :rows_examined, Count, sets: true
904
+ attribute :rust_rows_examined, Count, sets: true
905
+ attribute :aggregates_examined, Count, sets: true
906
+ attribute :reason, Report, sets: true
907
+ attribute :parity, Parity, sets: true
908
+ attribute :unchecked, list_of(Limit), sets: true
909
+ attribute :released, Switch, sets: true
910
+ attribute :kept, Report, optional: true, sets: true
911
+
912
+
913
+ emits RehearsalAudited
914
+ end
915
+
916
+ command "Judge" do
917
+ role "System"
918
+ goal "Record that the mint would go through: the domain booted, an edge leads on where one is needed, and nothing is refused"
919
+
920
+ reference_to RehearsalRun
921
+ attribute :verdict, Verdict, sets: true
922
+ attribute :refusal_total, Count
923
+ attribute :edge_present, Switch
924
+
925
+ given("a rehearsal that finds a refused row would not mint") { refusal_total.value == 0 }
926
+ given("a rehearsal judged to mint names that verdict") { verdict.value == "would_mint" }
927
+
928
+
929
+ emits RehearsalJudged
930
+ end
931
+
932
+ command "Withhold" do
933
+ role "System"
934
+ goal "Record that the mint would not go through, which of the three ways, and what it would say"
935
+
936
+ reference_to RehearsalRun
937
+ attribute :verdict, Verdict, sets: true
938
+ attribute :refusal, Report, sets: true
939
+
940
+ given("a withheld rehearsal names how the mint would stop") { verdict.value != "would_mint" }
941
+
942
+
943
+ emits RehearsalWithheld
944
+ end
945
+
946
+ command "Refuse" do
947
+ role "System"
948
+ goal "Record that the rehearsal was not run: the subject, the pin or the store was not admitted, and why"
949
+
950
+ reference_to RehearsalRun
951
+ attribute :refusal, Report, sets: true
952
+
953
+
954
+ emits RehearsalRefused
955
+ end
956
+
957
+ command "Fail" do
958
+ role "System"
959
+ goal "Record that the rehearsal broke after it began, and why"
960
+
961
+ reference_to RehearsalRun
962
+ attribute :refusal, Report, sets: true
963
+
964
+
965
+ emits RehearsalFailed
966
+ end
967
+
968
+ query "RehearsalOutcome" do
969
+ description "How one rehearsal ended: its status and verdict, and every fact it brought back. A run is kept by the process that made it, so a run this process does not hold is refused as unknown; `request` waits for its reactions and prints the whole outcome."
970
+ attribute :run, RunKey
971
+ where(run: :run)
972
+ order_by :run
973
+ end
974
+
975
+ query "Withheld" do
976
+ description "Every rehearsal of this process whose answer was that the mint would not go through."
977
+ where(status: "withheld")
978
+ order_by :run
979
+ end
980
+ end
981
+
982
+ policy "SurveyWhenRehearsalRequested" do
983
+ on "RehearsalRun.RehearsalRequested"
984
+ ask :survey, with: { run: :run }
985
+ end
986
+
987
+ policy "RefuseWhenStoreNotAdmitted" do
988
+ on "RehearsalRun.StoreRefused"
989
+ trigger RehearsalRun::Refuse, with: { refusal: :refusal }
990
+ end
991
+
992
+ policy "RecordBootWhenStoreSurveyed" do
993
+ on "RehearsalRun.StoreSurveyed"
994
+ where { booted.value }
995
+ trigger RehearsalRun::Boot, with: { booted: :booted, host_version: :host_version, store: :store, mode: :mode,
996
+ before: :before, after: :after, minting: :minting,
997
+ environment_loaded: :environment_loaded, schema_used: :schema_used,
998
+ eras_held: :eras_held, journal_entries: :journal_entries,
999
+ head_rows: :head_rows, census: :census, copy_empty: :copy_empty,
1000
+ copy_note: :copy_note, released: :released, kept: :kept }
1001
+ end
1002
+
1003
+ # A copy that holds none of the domain's rows is not rehearsed: there is nothing to audit, and a
1004
+ # clean answer over it would be a confident wrong one. The survey has already dropped it.
1005
+ policy "WithholdWhenTheCopyHoldsNothing" do
1006
+ on "RehearsalRun.RehearsalBooted"
1007
+ where { copy_empty.value }
1008
+ trigger RehearsalRun::Withhold, with: { verdict: "empty_copy", refusal: :copy_note }
1009
+ end
1010
+
1011
+ # A domain that does not load is an answer, not a breakdown: it is what the mint would be
1012
+ # stopped by, so it is judged, not failed.
1013
+ policy "WithholdWhenSubjectDoesNotBoot" do
1014
+ on "RehearsalRun.StoreSurveyed"
1015
+ where { !booted.value }
1016
+ trigger RehearsalRun::Withhold, with: { verdict: "cannot_boot", refusal: :boot_error }
1017
+ end
1018
+
1019
+ policy "FailWhenExaminationRefused" do
1020
+ on "RehearsalRun.ExamineRefused"
1021
+ trigger RehearsalRun::Fail, with: { refusal: :refusal }
1022
+ end
1023
+
1024
+ policy "ExamineWhenBooted" do
1025
+ on "RehearsalRun.RehearsalBooted"
1026
+ where { !copy_empty.value }
1027
+ ask :examine, with: { run: :run }
1028
+ end
1029
+
1030
+ policy "RecordAuditWhenStoreExamined" do
1031
+ on "RehearsalRun.StoreExamined"
1032
+ trigger RehearsalRun::Audit, with: { minting: :minting, edge_present: :edge_present,
1033
+ refused_rows: :refused_rows, refusal_total: :refusal_total,
1034
+ audited: :audited, rows_examined: :rows_examined,
1035
+ rust_rows_examined: :rust_rows_examined,
1036
+ aggregates_examined: :aggregates_examined, reason: :reason,
1037
+ parity: :parity, unchecked: :unchecked,
1038
+ released: :released, kept: :kept }
1039
+ end
1040
+
1041
+ policy "JudgeWhenNothingWouldStopTheMint" do
1042
+ on "RehearsalRun.RehearsalAudited"
1043
+ where do
1044
+ (minting.value != "next" || edge_present.value) && refusal_total.value == 0
1045
+ end
1046
+ trigger RehearsalRun::Judge, with: { verdict: "would_mint", refusal_total: :refusal_total,
1047
+ edge_present: :edge_present }
1048
+ end
1049
+
1050
+ policy "WithholdWhenNoEdgeLeadsOn" do
1051
+ on "RehearsalRun.RehearsalAudited"
1052
+ where { minting.value == "next" && !edge_present.value }
1053
+ trigger RehearsalRun::Withhold, with: { verdict: "needs_edge",
1054
+ refusal: "no translation edge leads the held era to this shape" }
1055
+ end
1056
+
1057
+ policy "WithholdWhenTheMintWouldRefuse" do
1058
+ on "RehearsalRun.RehearsalAudited"
1059
+ where do
1060
+ (minting.value != "next" || edge_present.value) && refusal_total.value > 0
1061
+ end
1062
+ trigger RehearsalRun::Withhold, with: { verdict: "would_refuse",
1063
+ refusal: "the mint would refuse: see the refused rows" }
1064
+ end
1065
+ end
1066
+ end