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
@@ -51,7 +51,7 @@ Hecks.bluebook "QualityControl" do
51
51
  # Comma-joined mode names recorded at release from what the runner inferred. Stored so
52
52
  # `EligibleFor` can answer why a mode never ran; inference at sweep time still decides.
53
53
  attribute :capabilities, Capabilities
54
- attribute :reason, TargetReason
54
+ attribute :reason, TargetReason, optional: true
55
55
 
56
56
  value_object "TargetReference" do
57
57
  attribute :value, String, matches: :present
@@ -352,7 +352,7 @@ Hecks.bluebook "QualityControl" do
352
352
  attribute :reference, SweepReference
353
353
  attribute :engineer, Engineer
354
354
  attribute :made, CheckCount
355
- attribute :notes, SweepNotes
355
+ attribute :notes, SweepNotes, optional: true
356
356
  # A counter, not a flag (a sweep can bend several gates) or a list (`where` cannot test
357
357
  # emptiness).
358
358
  attribute :waived, WaiverCount
@@ -747,12 +747,12 @@ Hecks.bluebook "QualityControl" do
747
747
  attribute :submitter, Submitter
748
748
  attribute :order, BugOrder
749
749
  attribute :tags, list_of(Tag)
750
- attribute :site, BugSite
751
- attribute :cause, BugCause
752
- attribute :commit, CommitRef
753
- attribute :verification, Verification
754
- attribute :reason, BugReason
755
- attribute :next_step, NextStep
750
+ attribute :site, BugSite, optional: true
751
+ attribute :cause, BugCause, optional: true
752
+ attribute :commit, CommitRef, optional: true
753
+ attribute :verification, Verification, optional: true
754
+ attribute :reason, BugReason, optional: true
755
+ attribute :next_step, NextStep, optional: true
756
756
  attribute :waived, WaiverCount
757
757
  # The same signature as `Sweep.waived_by`; absent until a person waives.
758
758
  attribute :waived_by, WaivedBy, optional: true
@@ -1207,6 +1207,14 @@ Hecks.bluebook "QualityControl" do
1207
1207
  order_by :sequence
1208
1208
  end
1209
1209
 
1210
+ # `hecks quality_control bug.fix_and_land --bug BUG#n` is the script. It is a query because the
1211
+ # records it writes are the Bug commands above, and the branch, commit, landing and push live
1212
+ # outside the ledger. It stops, and writes nothing, on a bug triaged bigger.
1213
+ query "FixAndLand" do
1214
+ description "Takes one self-contained bug through a fix on a fresh branch, the quick gate on that exact commit, a landing on local main and a push through the push train. A bigger bug stops here, untouched."
1215
+ order_by :sequence
1216
+ end
1217
+
1210
1218
  query "All" do
1211
1219
  description "Every bug ever logged — what a runner mints the next reference from."
1212
1220
  order_by :sequence
@@ -1225,8 +1233,8 @@ Hecks.bluebook "QualityControl" do
1225
1233
  attribute :citation, AngleCitation
1226
1234
  attribute :proposer, Proposer
1227
1235
  attribute :proposed_at, Instant
1228
- attribute :resolution, AngleResolution
1229
- attribute :reason, AngleReason
1236
+ attribute :resolution, AngleResolution, optional: true
1237
+ attribute :reason, AngleReason, optional: true
1230
1238
 
1231
1239
  value_object "AngleReference" do
1232
1240
  attribute :value, String, matches: :present
@@ -1825,7 +1833,7 @@ Hecks.bluebook "QualityControl" do
1825
1833
  attribute :number, ImprovementNumber
1826
1834
  attribute :url, ImprovementUrl
1827
1835
  attribute :branch, ImprovementBranch
1828
- attribute :commit, CommitRef
1836
+ attribute :commit, CommitRef, optional: true
1829
1837
  attribute :title, ImprovementTitle
1830
1838
  # See `Patch.opened_at`.
1831
1839
  attribute :opened_at, Instant
@@ -1967,6 +1975,822 @@ Hecks.bluebook "QualityControl" do
1967
1975
  end
1968
1976
  end
1969
1977
 
1978
+ # The quick gate run on local main, in a temporary worktree of it. One record per commit checked, so a
1979
+ # tick that finds the same commit again does not log the same red checks twice.
1980
+ aggregate "MainCheck" do
1981
+ description "One run of the quick gate on local main at one commit, and whether every one of its checks came back green."
1982
+
1983
+ identified_by :reference
1984
+
1985
+ attribute :reference, MainCommit
1986
+ attribute :verdict, one_of("green", "red")
1987
+ attribute :red_checks, RedCount
1988
+
1989
+ value_object "MainCommit" do
1990
+ attribute :value, String, matches: :git_sha
1991
+ end
1992
+
1993
+ value_object "RedCount" do
1994
+ attribute :value, Integer, default: 0
1995
+ invariant("a count of red checks is not negative") { !value.negative? }
1996
+ end
1997
+
1998
+ # Written as soon as the gate has answered, before any red check is logged or fixed, so the record
1999
+ # says what the gate said even when what follows fails.
2000
+ command "Record" do
2001
+ role "QA engineer"
2002
+ goal "Write down what the quick gate said about one commit of main"
2003
+
2004
+ attribute :reference, MainCommit
2005
+ attribute :verdict, one_of("green", "red")
2006
+ attribute :red_checks, RedCount
2007
+
2008
+ given("a red verdict names a red check, and a green one names none") do
2009
+ (verdict.value == "red" && red_checks.value.positive?) || (verdict.value == "green" && red_checks.value == 0)
2010
+ end
2011
+
2012
+ emits "MainCheckRecorded"
2013
+ end
2014
+
2015
+ # `hecks quality_control main_check.check_main` is the tick's step. It answers from the record when the
2016
+ # commit has one; otherwise it runs the gate, logs each red check as a bug and fixes the self-contained
2017
+ # ones. It is a query because it reads the commit and runs the gate; every write it makes is a
2018
+ # command of the Bug and Sweep aggregates.
2019
+ query "CheckMain" do
2020
+ description "Runs the quick gate on local main in a temporary worktree of it and records the verdict, logging each red check as a bug."
2021
+ order_by :reference
2022
+ end
2023
+
2024
+ query "All" do
2025
+ description "Every commit of main the quick gate has been run on, with its verdict."
2026
+ order_by :reference
2027
+ end
2028
+ end
2029
+
2030
+ # The event pump: each attached domain's policies read the events past their cursors and react to
2031
+ # them. The pump's own writes are the cursors below; it appends to no domain's event log.
2032
+ aggregate "EventCursor" do
2033
+ description "How far one consumer has read one domain's event log, as the count of entries it has reacted to. One row per (log, consumer)."
2034
+
2035
+ identified_by :key
2036
+
2037
+ attribute :key, CursorKey
2038
+ attribute :log, CursorDomain
2039
+ attribute :consumer, CursorDomain
2040
+ attribute :position, CursorPosition
2041
+ attribute :read_at, CursorReadAt, optional: true
2042
+
2043
+ value_object "CursorKey" do
2044
+ attribute :value, String, matches: :present
2045
+ invariant("a cursor is keyed by its log and consumer") { !value.to_s.empty? }
2046
+ end
2047
+
2048
+ value_object "CursorReadAt" do
2049
+ attribute :value, String, matches: :present
2050
+ end
2051
+
2052
+ value_object "CursorDomain" do
2053
+ attribute :value, String, matches: :present
2054
+ invariant("a cursor names its domain") { !value.to_s.empty? }
2055
+ end
2056
+
2057
+ value_object "CursorPosition" do
2058
+ attribute :value, Integer, default: 0
2059
+ invariant("a position is not negative") { !value.negative? }
2060
+ end
2061
+
2062
+ command "Start" do
2063
+ role "QA engineer"
2064
+ goal "Open a consumer's cursor on one domain's event log, at the start of the log"
2065
+
2066
+ attribute :key, CursorKey
2067
+ attribute :log, CursorDomain
2068
+ attribute :consumer, CursorDomain
2069
+
2070
+ emits "CursorStarted"
2071
+ end
2072
+
2073
+ # The pump passes only the position it has just reacted to, so a cursor moves forward in practice.
2074
+ command "Advance" do
2075
+ role "QA engineer"
2076
+ goal "Move one consumer's cursor past the entries it has reacted to"
2077
+
2078
+ attribute :position, CursorPosition, sets: true
2079
+
2080
+ emits "CursorAdvanced"
2081
+ end
2082
+
2083
+ query "All" do
2084
+ description "Every cursor the event pump holds, with the position each consumer has read to."
2085
+ order_by :key
2086
+ end
2087
+ end
2088
+
2089
+ # One policy's reaction to one event, recorded once the policy's command has answered: delivered or
2090
+ # refused. The pump checks a row before it runs the policy, so a reaction already on the ledger is not
2091
+ # run again, whatever the cursor says. Keyed by (consumer, event, policy), so the event's other policies
2092
+ # for the same consumer still run.
2093
+ aggregate "EventReaction" do
2094
+ description "A policy's reaction to one event, once its command has answered. One row per (consumer, event, policy)."
2095
+
2096
+ identified_by :key
2097
+
2098
+ attribute :key, ReactionKey
2099
+ attribute :consumer, ReactionConsumer
2100
+ attribute :event_id, ReactionEvent
2101
+ attribute :policy, ReactionPolicy
2102
+
2103
+ value_object "ReactionKey" do
2104
+ attribute :value, String, matches: :present
2105
+ invariant("a reaction is keyed by its consumer, event and policy") { !value.to_s.empty? }
2106
+ end
2107
+
2108
+ value_object "ReactionConsumer" do
2109
+ attribute :value, String, matches: :present
2110
+ invariant("a reaction names its consumer") { !value.to_s.empty? }
2111
+ end
2112
+
2113
+ value_object "ReactionEvent" do
2114
+ attribute :value, String, matches: :present
2115
+ invariant("a reaction names the event it answered") { !value.to_s.empty? }
2116
+ end
2117
+
2118
+ value_object "ReactionPolicy" do
2119
+ attribute :value, String, matches: :present
2120
+ invariant("a reaction names its policy") { !value.to_s.empty? }
2121
+ end
2122
+
2123
+ command "Record" do
2124
+ role "QA engineer"
2125
+ goal "Record that one consumer's policy has answered one event, so the pump does not run it again"
2126
+
2127
+ attribute :key, ReactionKey
2128
+ attribute :consumer, ReactionConsumer
2129
+ attribute :event_id, ReactionEvent
2130
+ attribute :policy, ReactionPolicy
2131
+
2132
+ emits "EventReacted"
2133
+ end
2134
+
2135
+ query "All" do
2136
+ description "Every reaction the event pump has recorded, by its key."
2137
+ order_by :key
2138
+ end
2139
+ end
2140
+
2141
+ # One run of the event pump, requested as a command and answered by the `PumpTools` port, which runs
2142
+ # `hecks quality_control qa_event_pump`. The QA tick runs the same pump as its last step.
2143
+ aggregate "EventPump" do
2144
+ description "One run of the event pump: every attached domain's policies reacting to the events past their cursors, and what each reaction answered."
2145
+
2146
+ identified_by :run
2147
+
2148
+ attribute :run, PumpRun
2149
+
2150
+ value_object "PumpRun" do
2151
+ attribute :value, String, matches: :present
2152
+ invariant("a pump run is named") { !value.to_s.empty? }
2153
+ end
2154
+
2155
+ command "Pump" do
2156
+ role "QA engineer"
2157
+ goal "Run the event pump once: each attached domain's policies react to the events past their cursors, and every refusal is named"
2158
+
2159
+ attribute :run, PumpRun
2160
+
2161
+ emits "PumpRequested"
2162
+ end
2163
+ end
2164
+
2165
+ policy "PumpOnRequest" do
2166
+ on "EventPump.PumpRequested"
2167
+ ask :execute, with: { run: :run }
2168
+ end
2169
+
2170
+ # The maintenance of local main as events and policies. A coder's `Submission.WorkSubmitted` starts
2171
+ # a run. Each step's body is an `ask` of a port the `MainMaintenance` adapter answers: the quick gate,
2172
+ # the reconcile, the push through the train. The answer is an event, and a policy turns each event into
2173
+ # the next step. A refusal is a named event, and nothing follows it.
2174
+ aggregate "Maintenance" do
2175
+ description "One run of local main's maintenance: the quick gate on a submitted commit, the reconcile, and the push through the train."
2176
+
2177
+ identified_by :run
2178
+
2179
+ attribute :run, MaintenanceRun
2180
+ attribute :sha, MaintenanceSha
2181
+ # The gate's colour and the reconcile's verdict. A run opened only to mint an era (`MintEra`) never
2182
+ # runs the gate or the reconcile, so its row holds neither.
2183
+ attribute :color, one_of("green", "red"), optional: true
2184
+ attribute :verdict, one_of("reported", "written", "refused"), optional: true
2185
+
2186
+ value_object "MaintenanceRun" do
2187
+ attribute :value, String, matches: :present
2188
+ invariant("a run names its branch") { !value.to_s.empty? }
2189
+ end
2190
+
2191
+ value_object "MaintenanceSha" do
2192
+ attribute :value, String, matches: :git_sha
2193
+ end
2194
+
2195
+ # The era a mint created, as the Minted event carries it.
2196
+ value_object "MintedEra" do
2197
+ attribute :value, Integer
2198
+ end
2199
+
2200
+ # Opens a run for a submitted commit of main; the gate is the first step it asks for.
2201
+ command "Start" do
2202
+ role "QA engineer"
2203
+ goal "Open the maintenance of main for one submitted commit"
2204
+
2205
+ attribute :run, MaintenanceRun
2206
+ attribute :sha, MaintenanceSha
2207
+
2208
+ emits "RunStarted"
2209
+ end
2210
+
2211
+ # Refuses a red gate: the policy that reads `GateVerdict` red calls it, and nothing reconciles or pushes.
2212
+ command "RefuseGate" do
2213
+ role "QA engineer"
2214
+ goal "Stop a run whose quick gate on main is red"
2215
+
2216
+ attribute :run, MaintenanceRun
2217
+ attribute :color, one_of("green", "red")
2218
+
2219
+ given("only a red verdict is refused") { color.value == "red" }
2220
+
2221
+ emits "GateRefused"
2222
+ end
2223
+
2224
+ # Asks for the reconcile once the gate is green.
2225
+ command "RequestReconcile" do
2226
+ role "QA engineer"
2227
+ goal "Ask for the reconcile of a commit whose quick gate is green"
2228
+
2229
+ attribute :run, MaintenanceRun
2230
+ attribute :sha, MaintenanceSha
2231
+ attribute :color, one_of("green", "red")
2232
+
2233
+ given("only a green gate is reconciled") { color.value == "green" }
2234
+
2235
+ emits "ReconcileRequested"
2236
+ end
2237
+
2238
+ # Asks for the push once the reconcile has not refused and the gate is green.
2239
+ command "RequestPush" do
2240
+ role "QA engineer"
2241
+ goal "Ask for the push of a commit whose gate is green and whose reconcile did not refuse"
2242
+
2243
+ attribute :run, MaintenanceRun
2244
+ attribute :sha, MaintenanceSha
2245
+ attribute :color, one_of("green", "red")
2246
+ attribute :verdict, one_of("reported", "written", "refused")
2247
+
2248
+ given("the reconcile did not refuse and the gate is green") do
2249
+ verdict.value != "refused" && color.value == "green"
2250
+ end
2251
+
2252
+ emits "PushRequested"
2253
+ end
2254
+
2255
+ value_object "MintVerdict" do
2256
+ attribute :value, String, one_of: ["would_mint", "would_refuse", "needs_edge", "cannot_boot", "empty_copy"]
2257
+ end
2258
+
2259
+ # Records what the rehearsal of a domain's next era concluded, at the ledger watermark it read. The mint
2260
+ # policy reads the verdict off `MintRequested`, so a mint is only ever asked for a rehearsal that said
2261
+ # would_mint.
2262
+ command "RecordRehearsalVerdict" do
2263
+ role "QA engineer"
2264
+ goal "Record what the rehearsal of a domain's next era concluded, and the watermark it read"
2265
+
2266
+ attribute :run, MaintenanceRun
2267
+ attribute :domain, String
2268
+ attribute :watermark, Integer
2269
+ attribute :rehearsal_verdict, MintVerdict
2270
+
2271
+ emits "RehearsalVerdict"
2272
+ end
2273
+
2274
+ # The confirmation of a mint: the owner's `--confirm` flag, which the launcher reads as a Boolean. A mint
2275
+ # the auto-mint rule covers runs without it; every other mint needs it.
2276
+ value_object "Confirmation" do
2277
+ attribute :value, Boolean
2278
+ end
2279
+
2280
+ # Why a mint was refused, as the refusal the mint entry point names. A held mint says "needs owner
2281
+ # approval", which the approval policy reads.
2282
+ value_object "MintRefusal" do
2283
+ attribute :value, String
2284
+ end
2285
+
2286
+ # The single entry point for a mint of a domain's next era. It is the only command that asks for a mint:
2287
+ # a boot never mints, and the mint names the commit its landing puts on main, so the ledger and main move
2288
+ # together. The rehearsal ref and the expected watermark are checked against the live ledger by the era check.
2289
+ # `refusal_total` is the rehearsal's refusal count and `ledger_dir` the bluebook directory of the ledger
2290
+ # the era belongs to (the QualityControl ledger when omitted). A mint with no `confirm` runs only when
2291
+ # the auto-mint rule (`AutoMintAdditive`) holds; the mint entry point checks it.
2292
+ command "MintEra" do
2293
+ role "QA engineer"
2294
+ goal "Mint a domain's next era, against the rehearsal of that same era and the watermark it read"
2295
+ attribute :run, MaintenanceRun
2296
+ attribute :domain, String
2297
+ attribute :era, Integer
2298
+ attribute :sha, MaintenanceSha
2299
+ attribute :branch, String
2300
+ attribute :rehearsal_ref, String
2301
+ attribute :watermark, Integer
2302
+ attribute :rehearsal_verdict, MintVerdict
2303
+ attribute :refusal_total, Integer, optional: true
2304
+ attribute :ledger_dir, String, optional: true
2305
+ attribute :confirm, Confirmation, optional: true
2306
+
2307
+ emits "MintRequested"
2308
+ end
2309
+
2310
+ # Refuses a mint whose rehearsal did not say would_mint, and nothing mints or lands after it. It also
2311
+ # carries the refusal the mint entry point named when it held a mint for the owner.
2312
+ command "RefuseMint" do
2313
+ role "QA engineer"
2314
+ goal "Stop a mint whose rehearsal did not say would_mint"
2315
+
2316
+ attribute :run, MaintenanceRun
2317
+ attribute :domain, String
2318
+ attribute :era, Integer
2319
+ attribute :rehearsal_verdict, MintVerdict
2320
+ attribute :refusal, MintRefusal, optional: true
2321
+
2322
+ given("only a rehearsal that did not say would_mint is refused") { rehearsal_verdict.value != "would_mint" }
2323
+
2324
+ emits "MintRefused"
2325
+ end
2326
+ end
2327
+
2328
+ # One release PR: the bump of the version on main, opened as a PR and approved on GitHub by the owner. The
2329
+ # approval is written as the release trailer on the merge, which is the line `Hecks::Release::Approval`
2330
+ # reads. A PR is approved only when every auto-approval condition holds (see ReleaseCondition); a failed
2331
+ # condition is a named refusal and nothing is approved.
2332
+ aggregate "ReleasePR" do
2333
+ description "One release PR: the version bump opened on GitHub, approved by the owner only when every auto-approval condition holds."
2334
+
2335
+ identified_by :release
2336
+
2337
+ attribute :release, ReleaseVersion
2338
+ attribute :branch, ReleaseBranch
2339
+ attribute :sha, MaintenanceSha
2340
+ attribute :verdict, one_of("open", "approved", "refused")
2341
+
2342
+ value_object "ReleaseBranch" do
2343
+ attribute :value, String, matches: :present
2344
+ end
2345
+
2346
+ value_object "ReleaseVersion" do
2347
+ attribute :value, String
2348
+ invariant("a release names a semantic version") { value.to_s.match?(/\A[0-9]+\.[0-9]+\.[0-9]+\z/) }
2349
+ end
2350
+
2351
+ # The four conditions an approval needs, each named so a refusal says which one failed. `met` is the only
2352
+ # value an approval accepts; the Ruby judge (`Hecks::Release::Conditions.judge`) answers the first failure
2353
+ # in this order: the commit is on stable's head, the required checks passed on it, the CHANGELOG has a
2354
+ # dated `## [<version>]` heading, and every version file names the same version.
2355
+ value_object "ReleaseCondition" do
2356
+ attribute :value, String, one_of: ["met", "not_on_stable_head", "checks_not_green",
2357
+ "changelog_undated", "version_mismatch"]
2358
+ end
2359
+
2360
+ # The owner who approves each release PR. The trailer line names this person; no other name is approved.
2361
+ value_object "ReleaseApprover" do
2362
+ attribute :value, String, one_of: ["Chris Young"]
2363
+ end
2364
+
2365
+ # The commit-message trailer an approval writes. It is the `release_trailer` of the stable `Lane` row
2366
+ # (Vocabulary), which `Hecks::Release::Approval` reads, so the check accepts what the policy writes.
2367
+ value_object "ReleaseTrailer" do
2368
+ attribute :value, String, one_of: ["Release-Approved-By"]
2369
+ end
2370
+
2371
+ # Opens the release PR for a version bump on a branch. The open is answered by the `ReleaseGh` port.
2372
+ command "Open" do
2373
+ role "Release owner"
2374
+ goal "Open the release PR for a version bump on main, so the owner can approve it on GitHub"
2375
+
2376
+ attribute :release, ReleaseVersion
2377
+ attribute :branch, ReleaseBranch
2378
+ attribute :sha, MaintenanceSha
2379
+
2380
+ emits "ReleaseOpenRequested"
2381
+ end
2382
+
2383
+ # Records the result of the four auto-approval conditions for one release PR. The caller names the approver
2384
+ # and the trailer, which the approval policy passes on to the approval.
2385
+ command "Check" do
2386
+ role "Release owner"
2387
+ goal "Record which auto-approval condition held for a release PR, naming the first one that failed"
2388
+
2389
+ attribute :release, ReleaseVersion
2390
+ attribute :sha, MaintenanceSha
2391
+ attribute :condition, ReleaseCondition
2392
+ attribute :approver, ReleaseApprover
2393
+ attribute :trailer, ReleaseTrailer
2394
+
2395
+ emits "ReleaseChecked"
2396
+ end
2397
+
2398
+ # Approves a release PR whose conditions all held. Only a condition of `met` is approved; the trailer
2399
+ # is then written on the merge by the `ReleaseGh` port.
2400
+ command "Approve" do
2401
+ role "Release owner"
2402
+ goal "Approve a release PR once every auto-approval condition holds, writing the release trailer for the owner"
2403
+
2404
+ attribute :release, ReleaseVersion
2405
+ attribute :sha, MaintenanceSha
2406
+ attribute :condition, ReleaseCondition
2407
+ attribute :approver, ReleaseApprover
2408
+ attribute :trailer, ReleaseTrailer
2409
+
2410
+ given("only a release whose conditions all held is approved") { condition.value == "met" }
2411
+
2412
+ emits "ReleaseApproved"
2413
+ end
2414
+
2415
+ # Refuses a release PR one of whose conditions failed, and names that condition.
2416
+ command "Refuse" do
2417
+ role "Release owner"
2418
+ goal "Refuse a release PR, naming the auto-approval condition that failed"
2419
+
2420
+ attribute :release, ReleaseVersion
2421
+ attribute :condition, ReleaseCondition
2422
+
2423
+ given("only a release with a failed condition is refused") { condition.value != "met" }
2424
+
2425
+ emits "ReleaseRefused"
2426
+ end
2427
+ end
2428
+
2429
+ # What remote CI said about one commit of a repository's main, once every job it ran for that
2430
+ # commit
2431
+ # settled. The Runner adapter answers `Check`; a green verdict is announced as `CiGreen`, and a
2432
+ # red one
2433
+ # as `CiRed` with the failing jobs. Lives here, beside the roll it feeds: a policy reads only
2434
+ # events
2435
+ # its own bluebook emits.
2436
+ aggregate "Head" do
2437
+ description "One commit of a repository's main, and whether remote CI passed every job it ran for that commit."
2438
+
2439
+ identified_by :commit
2440
+
2441
+ attribute :commit, HeadCommit
2442
+ attribute :branch, HeadBranch
2443
+ attribute :repo, HeadRepo
2444
+ attribute :color, one_of("green", "red")
2445
+ attribute :failing_jobs, FailingJobs
2446
+
2447
+ value_object "HeadCommit" do
2448
+ attribute :value, String, pattern: '^[0-9a-f]{40}$'
2449
+ end
2450
+
2451
+ value_object "HeadBranch" do
2452
+ attribute :value, String, matches: :present
2453
+ invariant("a head names its branch") { !value.to_s.empty? }
2454
+ end
2455
+
2456
+ value_object "HeadRepo" do
2457
+ # GitHub's `owner/name`.
2458
+ attribute :value, String, pattern: '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$'
2459
+ end
2460
+
2461
+ # The failing jobs of a red run, comma-separated; empty for a green one.
2462
+ value_object "FailingJobs" do
2463
+ attribute :value, String, default: ""
2464
+ end
2465
+
2466
+ # Asks remote CI about one commit. Only main is judged: a commit on a branch says nothing about
2467
+ # main.
2468
+ command "Request" do
2469
+ role "CI engineer"
2470
+ goal "Ask remote CI what it said about one commit of a repository's main"
2471
+
2472
+ attribute :commit, HeadCommit
2473
+ attribute :branch, HeadBranch
2474
+ attribute :repo, HeadRepo
2475
+
2476
+ given("only main is judged") { branch.value == "main" }
2477
+
2478
+ emits "HeadRequested"
2479
+ end
2480
+
2481
+ # Records a green verdict. Refused for any other colour: a red head is never announced as
2482
+ # green.
2483
+ command "Green" do
2484
+ role "System"
2485
+ goal "Announce that remote CI passed every job it ran for one commit of main"
2486
+
2487
+ attribute :commit, HeadCommit
2488
+ attribute :branch, HeadBranch
2489
+ attribute :repo, HeadRepo
2490
+ attribute :color, one_of("green", "red")
2491
+
2492
+ given("only a green verdict is announced") { color.value == "green" }
2493
+
2494
+ emits "CiGreen"
2495
+ end
2496
+
2497
+ # Records a red verdict, naming the jobs that failed. Refused for any other colour.
2498
+ command "Red" do
2499
+ role "System"
2500
+ goal "Announce that remote CI refused one commit of main, and which jobs failed"
2501
+
2502
+ attribute :commit, HeadCommit
2503
+ attribute :repo, HeadRepo
2504
+ attribute :color, one_of("green", "red")
2505
+ attribute :failing_jobs, FailingJobs
2506
+
2507
+ given("only a red verdict names the jobs that failed") do
2508
+ color.value == "red" && !failing_jobs.value.to_s.empty?
2509
+ end
2510
+
2511
+ emits "CiRed"
2512
+ end
2513
+ end
2514
+
2515
+ # One spec file that is red on main, keyed `red-<spec path slug>`. A red run reports each failing
2516
+ # spec file; the first report opens the row and a later one only updates what it knew, so a spec
2517
+ # red for days is one row, and `since` is the day it first went red. A settled run that no longer
2518
+ # fails the file clears it. Tickets mirrors it as a Work row for QA (`PlanWorkWhenSpecWentRed`, `FinishWorkWhenSpecWentGreen`).
2519
+ aggregate "RedSpec" do
2520
+ description "One spec file that is red on main: how many examples fail, the first failure, the run that saw it last, and the day it first went red."
2521
+
2522
+ identified_by :spec
2523
+
2524
+ attribute :spec, SpecKey
2525
+ attribute :path, SpecPath
2526
+ attribute :failures, FailureCount
2527
+ attribute :first_failure, FailureLine, optional: true
2528
+ attribute :examples, FailureLine, optional: true
2529
+ attribute :last_run, RunId
2530
+ attribute :commit, SpecCommit
2531
+ attribute :since, SeenOn
2532
+ attribute :title, WorkLine
2533
+ attribute :detail, WorkLine
2534
+ attribute :cleared_by, RunId, optional: true
2535
+
2536
+ value_object "SpecKey" do
2537
+ attribute :value, String, pattern: '^red-[a-z0-9_-]+$'
2538
+ end
2539
+
2540
+ value_object "SpecPath" do
2541
+ attribute :value, String, matches: :present
2542
+ end
2543
+
2544
+ value_object "FailureCount" do
2545
+ attribute :value, Integer
2546
+ invariant("a red spec has failing examples") { value.positive? }
2547
+ end
2548
+
2549
+ # Text as the failing run printed it, shortened by the reader.
2550
+ value_object "FailureLine" do
2551
+ attribute :value, String, default: ""
2552
+ end
2553
+
2554
+ # A line of the Work row the spec mirrors into.
2555
+ value_object "WorkLine" do
2556
+ attribute :value, String, matches: :present
2557
+ end
2558
+
2559
+ value_object "RunId" do
2560
+ attribute :value, String, matches: :present
2561
+ end
2562
+
2563
+ value_object "SpecCommit" do
2564
+ attribute :value, String, matches: :present
2565
+ end
2566
+
2567
+ # An ISO 8601 date, read from the clock by the run reader, never by the bluebook.
2568
+ value_object "SeenOn" do
2569
+ attribute :value, String, matches: :present
2570
+ end
2571
+
2572
+ # A cleared file that fails again goes back to red: the row reopens, it is never filed twice.
2573
+ lifecycle :status, default: "red" do
2574
+ mark :failure, "red"
2575
+ transition "Clear" => "green", from: "red"
2576
+ transition "Reopen" => "red", from: "green"
2577
+ end
2578
+
2579
+ # Opens the row for a spec file. A spec already red is not reported twice: see `Update`.
2580
+ command "Open" do
2581
+ role "System"
2582
+ goal "Record that a spec file is red on main"
2583
+
2584
+ attribute :spec, SpecKey, sets: true
2585
+ attribute :path, SpecPath, sets: true
2586
+ attribute :failures, FailureCount, sets: true
2587
+ attribute :first_failure, FailureLine, optional: true, sets: true
2588
+ attribute :examples, FailureLine, optional: true, sets: true
2589
+ attribute :last_run, RunId, sets: true
2590
+ attribute :commit, SpecCommit, sets: true
2591
+ attribute :since, SeenOn, sets: true
2592
+ attribute :title, WorkLine, sets: true
2593
+ attribute :detail, WorkLine, sets: true
2594
+
2595
+ emits "SpecWentRed"
2596
+ end
2597
+
2598
+ # A spec still red in a later run: what the latest run saw replaces what the row knew; `since` stays.
2599
+ command "Update" do
2600
+ role "System"
2601
+ goal "Record what a later red run saw of a spec file that was already red"
2602
+
2603
+ reference_to RedSpec
2604
+ attribute :failures, FailureCount, sets: true
2605
+ attribute :first_failure, FailureLine, optional: true, sets: true
2606
+ attribute :examples, FailureLine, optional: true, sets: true
2607
+ attribute :last_run, RunId, sets: true
2608
+ attribute :commit, SpecCommit, sets: true
2609
+ attribute :detail, WorkLine, sets: true
2610
+
2611
+ emits "SpecStillRed"
2612
+ end
2613
+
2614
+ # A spec that was cleared and failed again: what the new red run saw replaces what the row knew,
2615
+ # and `since` is the day it went red this time.
2616
+ command "Reopen" do
2617
+ role "System"
2618
+ goal "Record that a spec file cleared earlier is red on main again"
2619
+
2620
+ reference_to RedSpec
2621
+ attribute :failures, FailureCount, sets: true
2622
+ attribute :first_failure, FailureLine, optional: true, sets: true
2623
+ attribute :examples, FailureLine, optional: true, sets: true
2624
+ attribute :last_run, RunId, sets: true
2625
+ attribute :commit, SpecCommit, sets: true
2626
+ attribute :since, SeenOn, sets: true
2627
+ attribute :title, WorkLine, sets: true
2628
+ attribute :detail, WorkLine, sets: true
2629
+
2630
+ emits "SpecWentRedAgain"
2631
+ end
2632
+
2633
+ # `seen_in` is the run that last saw the file fail; a run that did see it fails to clear it.
2634
+ command "Clear" do
2635
+ role "System"
2636
+ goal "Record that a settled run of main no longer fails a spec file"
2637
+
2638
+ reference_to RedSpec
2639
+ attribute :run, RunId
2640
+ attribute :seen_in, RunId
2641
+
2642
+ given("a run that still saw the file fail does not clear it") { run.value != seen_in.value }
2643
+
2644
+ sets :cleared_by, to: :run
2645
+
2646
+ emits "SpecWentGreen"
2647
+ end
2648
+
2649
+ query "OnMain" do
2650
+ description "The red specs on main: every spec file still red, with the day it first went red and the run that last saw it fail."
2651
+ where(status: "red")
2652
+ order_by :since
2653
+ end
2654
+ end
2655
+
2656
+ # One CI run of main read for its failing spec files. The Reader port reports each failing file
2657
+ # to `RedSpec` and answers what the run settled to.
2658
+ aggregate "MainRun" do
2659
+ description "One CI run of main, read for the spec files it failed."
2660
+
2661
+ identified_by :run
2662
+
2663
+ attribute :run, MainRunId
2664
+ attribute :repo, HeadRepo
2665
+ attribute :commit, SpecCommit, optional: true
2666
+ attribute :settled, SettledFlag, optional: true
2667
+
2668
+ value_object "MainRunId" do
2669
+ attribute :value, String, matches: :present
2670
+ end
2671
+
2672
+ # "yes" once every job that runs specs finished, so a spec absent from the failures passed.
2673
+ value_object "SettledFlag" do
2674
+ attribute :value, String, default: ""
2675
+ end
2676
+
2677
+ command "Request" do
2678
+ role "CI engineer"
2679
+ goal "Ask for one CI run of main to be read for the spec files it failed"
2680
+
2681
+ attribute :run, MainRunId, sets: true
2682
+ attribute :repo, HeadRepo, sets: true
2683
+
2684
+ emits "MainRunReadRequested"
2685
+ end
2686
+
2687
+ command "Record" do
2688
+ role "System"
2689
+ goal "Keep how a read run settled"
2690
+
2691
+ reference_to MainRun
2692
+ attribute :commit, SpecCommit, sets: true
2693
+ attribute :settled, SettledFlag, sets: true
2694
+
2695
+ emits "MainRunRecorded"
2696
+ end
2697
+ end
2698
+
2699
+ # The image roll of one commit of embryonaut_platform's main. A commit whose remote CI is green
2700
+ # is
2701
+ # classified by the paths it changed: only the console container's inputs roll by themselves, and
2702
+ # anything else waits for a person. A commit rolls once; a second request finds the roll under
2703
+ # way.
2704
+ aggregate "ImageRoll" do
2705
+ description "One commit of embryonaut_platform's main: whether its container image was rolled, or waits for a person."
2706
+
2707
+ identified_by :commit
2708
+
2709
+ attribute :commit, CommitRef
2710
+ attribute :app, AppName
2711
+ attribute :paths, ChangedPaths
2712
+ attribute :outcome, one_of("done", "failed")
2713
+
2714
+ lifecycle :roll, default: "idle" do
2715
+ transition "Request" => "requested", from: "idle"
2716
+ transition "NeedsApproval" => "awaiting_approval", from: "idle"
2717
+ transition "Finish" => "finished", from: "requested"
2718
+ mark :terminal, "awaiting_approval", "finished"
2719
+ end
2720
+
2721
+ value_object "CommitRef" do
2722
+ attribute :value, String, pattern: '^[0-9a-f]{40}$'
2723
+ end
2724
+
2725
+ value_object "AppName" do
2726
+ attribute :value, String, matches: :present
2727
+ invariant("an app is named") { !value.to_s.empty? }
2728
+ end
2729
+
2730
+ value_object "RollBranch" do
2731
+ attribute :value, String, matches: :present
2732
+ end
2733
+
2734
+ value_object "RollRepo" do
2735
+ # GitHub's `owner/name`.
2736
+ attribute :value, String, pattern: '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$'
2737
+ end
2738
+
2739
+ # The changed paths of the commit, newline-separated, as the classifier read them.
2740
+ value_object "ChangedPaths" do
2741
+ attribute :value, String, default: ""
2742
+ end
2743
+
2744
+ # Takes a green commit of the platform's main into the roll's chain; the classifier answers
2745
+ # next.
2746
+ command "Consider" do
2747
+ role "System"
2748
+ goal "Take one green commit of embryonaut_platform's main into the image roll's chain"
2749
+
2750
+ attribute :commit, CommitRef
2751
+ attribute :branch, RollBranch
2752
+ attribute :repo, RollRepo
2753
+
2754
+ emits "RollConsidered"
2755
+ end
2756
+
2757
+ # Opens the roll of one classified commit; only an idle one may be requested.
2758
+ command "Request" do
2759
+ role "System"
2760
+ goal "Start the image roll of one commit whose changes touch only the console container's inputs"
2761
+
2762
+ attribute :commit, CommitRef
2763
+ attribute :app, AppName
2764
+
2765
+ emits "RollRequested"
2766
+ end
2767
+
2768
+ # Holds a commit whose changes reach past the container: a person releases it.
2769
+ command "NeedsApproval" do
2770
+ role "System"
2771
+ goal "Hold one commit whose changes reach past the container's inputs for a person to approve"
2772
+
2773
+ attribute :commit, CommitRef
2774
+ attribute :paths, ChangedPaths
2775
+
2776
+ emits "RollNeedsApproval"
2777
+ end
2778
+
2779
+ # Records how a requested roll ended, done or failed.
2780
+ command "Finish" do
2781
+ role "System"
2782
+ goal "Record how the image roll of one commit ended"
2783
+
2784
+ reference_to ImageRoll
2785
+ attribute :app, AppName
2786
+ attribute :status, one_of("done", "failed")
2787
+
2788
+ sets :outcome, to: :status
2789
+
2790
+ emits "RollDone"
2791
+ end
2792
+ end
2793
+
1970
2794
  # One CI run against one commit. A clearance is minted per commit, so a later commit is stale
1971
2795
  # by simply having none.
1972
2796
  aggregate "Clearance" do
@@ -2002,6 +2826,17 @@ Hecks.bluebook "QualityControl" do
2002
2826
  emits "ClearanceStarted"
2003
2827
  end
2004
2828
 
2829
+ # Start and ask CI in one step: the verdict comes back as `SuitePassed` or `SuiteFailed`, and
2830
+ # `ClearOnPass` and `RefuseOnFail` settle the record. `Start` alone records a verdict CI gave elsewhere.
2831
+ command "Check" do
2832
+ role "QA engineer"
2833
+ goal "Put a commit through CI and record the verdict it gives"
2834
+
2835
+ attribute :commit, CommitRef
2836
+
2837
+ emits "ClearanceChecked"
2838
+ end
2839
+
2005
2840
  command "Passed" do
2006
2841
  role "System"
2007
2842
  goal "Record that the suite went green against this commit"
@@ -2126,6 +2961,31 @@ Hecks.bluebook "QualityControl" do
2126
2961
  group_by :status, :number
2127
2962
  end
2128
2963
 
2964
+ # The fixer does the work of a fix; the ledger records each step it reports, so only these policies
2965
+ # write a bug's state after logging. Each names the fixer event it reacts to, and the Bug command
2966
+ # it records.
2967
+ policy "RecordClaimOnAttemptClaimed" do
2968
+ on "Attempt.AttemptClaimed"
2969
+ trigger Bug::Claim, with: { bug: :reference, held_by: :held_by, now: :now }
2970
+ end
2971
+
2972
+ policy "RecordInvestigationOnAttemptInvestigated" do
2973
+ on "Attempt.AttemptInvestigated"
2974
+ trigger Bug::Investigate, with: { bug: :reference, site: :site, cause: :cause }
2975
+ end
2976
+
2977
+ # The fix commit is recorded as the bug's fixed state; `BugCiWatch` starts on the `BugFixed` it emits.
2978
+ policy "RecordFixOnFixReady" do
2979
+ on "Attempt.FixReady"
2980
+ trigger Bug::Fix, with: { reference: :reference, commit: :commit }
2981
+ end
2982
+
2983
+ # A verified fix is the ledger's verified state, recorded with the evidence the fixer names.
2984
+ policy "RecordVerifyOnFixVerified" do
2985
+ on "Attempt.FixVerified"
2986
+ trigger Bug::Verify, with: { bug: :reference, evidence: :evidence }
2987
+ end
2988
+
2129
2989
  # `Ticket.Close` is the only way a ticket leaves `filed`, and only the outside can know it
2130
2990
  # happened, so the fact arrives by whichever route reaches us first.
2131
2991
  policy "CloseWhenClosedUpstream" do
@@ -2133,6 +2993,11 @@ Hecks.bluebook "QualityControl" do
2133
2993
  trigger Ticket::Close
2134
2994
  end
2135
2995
 
2996
+ policy "RunWhenChecked" do
2997
+ on "Clearance.ClearanceChecked"
2998
+ ask :run, with: { commit: :commit }
2999
+ end
3000
+
2136
3001
  # The adapter decides by answering or refusing, the only branch a policy can express.
2137
3002
  policy "ClearOnPass" do
2138
3003
  on "Clearance.SuitePassed"
@@ -2184,4 +3049,259 @@ Hecks.bluebook "QualityControl" do
2184
3049
  reason: { value: "a check surprised — a person releases with hecks quality_control query sweep.run <target> --release --notes" }
2185
3050
  }
2186
3051
  end
3052
+
3053
+ # A requested head is read from remote CI by the CiHead port; the answer is the verdict's event.
3054
+ policy "CheckHeadOnRequest" do
3055
+ on "Head.HeadRequested"
3056
+ ask :check, with: { commit: :commit, branch: :branch, repo: :repo }
3057
+ end
3058
+
3059
+ policy "GreenOnHeadChecked" do
3060
+ on "Head.HeadChecked"
3061
+ where { color.value == "green" }
3062
+ trigger Head::Green, with: { commit: :commit, branch: :branch, repo: :repo, color: :color }
3063
+ end
3064
+
3065
+ policy "RedOnHeadChecked" do
3066
+ on "Head.HeadChecked"
3067
+ where { color.value == "red" }
3068
+ trigger Head::Red, with: { commit: :commit, repo: :repo, color: :color, failing_jobs: :failing_jobs }
3069
+ end
3070
+
3071
+ # A run of main read for its failing spec files. The reader reports each failing file to RedSpec
3072
+ # (opening a row or updating it) before it answers.
3073
+ policy "ReadRunOnRequest" do
3074
+ on "MainRun.MainRunReadRequested"
3075
+ ask :read, with: { run: :run, repo: :repo }
3076
+ end
3077
+
3078
+ policy "RecordTheRunRead" do
3079
+ on "MainRun.MainRunRead"
3080
+ trigger MainRun::Record, with: { commit: :commit, settled: :settled }
3081
+ end
3082
+
3083
+ # A settled run clears every red spec it did not see fail; `Clear` refuses one it did, which stays open.
3084
+ policy "ClearSpecsOnSettledRun" do
3085
+ on "MainRun.MainRunRead"
3086
+ where { settled.value == "yes" }
3087
+ for_each "RedSpec.OnMain"
3088
+ trigger RedSpec::Clear, with: { spec: :spec, run: :run, seen_in: :last_run }
3089
+ end
3090
+
3091
+ # The image roll's chain. A green remote CI on embryonaut_platform's main is classified by the
3092
+ # `ImageRoll` port: the answer is `ImageClassified`, and a refusal (the change set unreadable)
3093
+ # ends the chain. Only the classifier's verdict decides; an infra commit is held, and its roll
3094
+ # needs a green quick gate on record.
3095
+ policy "RollImages" do
3096
+ on "Head.CiGreen"
3097
+ where { repo.value == "heckslabs/embryonaut_platform" }
3098
+ trigger ImageRoll::Consider, with: { commit: :commit, branch: :branch, repo: :repo }
3099
+ end
3100
+
3101
+ policy "ClassifyConsidered" do
3102
+ on "ImageRoll.RollConsidered"
3103
+ ask :classify, with: { commit: :commit, branch: :branch, repo: :repo }
3104
+ end
3105
+
3106
+ policy "RollWhenImageOnly" do
3107
+ on "ImageRoll.ImageClassified"
3108
+ where { kind.value == "image" }
3109
+ trigger ImageRoll::Request, with: { commit: :commit, app: :app }
3110
+ end
3111
+
3112
+ policy "HoldWhenInfra" do
3113
+ on "ImageRoll.ImageClassified"
3114
+ where { kind.value == "infra" }
3115
+ trigger ImageRoll::NeedsApproval, with: { commit: :commit, paths: :paths }
3116
+ end
3117
+
3118
+ policy "RunRollOnRequest" do
3119
+ on "ImageRoll.RollRequested"
3120
+ ask :roll, with: { commit: :commit, app: :app }
3121
+ end
3122
+
3123
+ policy "FinishOnRollAnswered" do
3124
+ on "ImageRoll.RollAnswered"
3125
+ trigger ImageRoll::Finish, with: { commit: :commit, app: :app, status: :status }
3126
+ end
3127
+
3128
+ policy "FinishOnRollRefused" do
3129
+ on "ImageRoll.RollRefused"
3130
+ trigger ImageRoll::Finish, with: { commit: :commit, app: :app, status: { value: "failed" } }
3131
+ end
3132
+
3133
+ # The main-maintenance chain, one policy per event. Each `ask` is answered by the `MainMaintenance` port;
3134
+ # each `trigger` is a command above. The events are the contract: `WorkSubmitted(branch, sha)` from the
3135
+ # coder side, `GateVerdict(run, sha, color)`, `ReconcileRequested`, `ReconcileDone(run, sha, color,
3136
+ # verdict)`, `PushRequested`, `Pushed(run, sha, origin_sha)`, and the refusals `GateRefused`,
3137
+ # `ReconcileRefused`, `PushRefused`.
3138
+ policy "StartOnSubmission" do
3139
+ on "Submission.WorkSubmitted"
3140
+ trigger Maintenance::Start, with: { run: :branch, sha: :sha }
3141
+ end
3142
+
3143
+ policy "GateOnStart" do
3144
+ on "Maintenance.RunStarted"
3145
+ ask :gate, with: { run: :run, sha: :sha }
3146
+ end
3147
+
3148
+ policy "RefuseOnRedGate" do
3149
+ on "Maintenance.GateVerdict"
3150
+ where { color.value == "red" }
3151
+ trigger Maintenance::RefuseGate, with: { run: :run, color: :color }
3152
+ end
3153
+
3154
+ policy "ReconcileOnGreenGate" do
3155
+ on "Maintenance.GateVerdict"
3156
+ where { color.value == "green" }
3157
+ trigger Maintenance::RequestReconcile, with: { run: :run, sha: :sha, color: :color }
3158
+ end
3159
+
3160
+ policy "ReconcileOnRequest" do
3161
+ on "Maintenance.ReconcileRequested"
3162
+ ask :reconcile, with: { run: :run, sha: :sha, color: :color }
3163
+ end
3164
+
3165
+ policy "PushOnReconciled" do
3166
+ on "Maintenance.ReconcileDone"
3167
+ where { verdict.value != "refused" && color.value == "green" }
3168
+ trigger Maintenance::RequestPush, with: { run: :run, sha: :sha, color: :color, verdict: :verdict }
3169
+ end
3170
+
3171
+ policy "PushOnRequest" do
3172
+ on "Maintenance.PushRequested"
3173
+ ask :push, with: { run: :run, sha: :sha }
3174
+ end
3175
+
3176
+ # The mint chain. `MintRequested` carries the rehearsal's verdict and the watermark it read; the mint is
3177
+ # asked only for a would_mint verdict, and the refusal is the same named event as every other refusal.
3178
+ # A mint's landing follows it in the same step; a failed landing is `MintStranded`, the event a refused
3179
+ # `Land` ask names.
3180
+ policy "RefuseMintWithoutVerdict" do
3181
+ on "Maintenance.MintRequested"
3182
+ where { rehearsal_verdict.value != "would_mint" }
3183
+ trigger Maintenance::RefuseMint, with: { run: :run, domain: :domain, era: :era, rehearsal_verdict: :rehearsal_verdict }
3184
+ end
3185
+
3186
+ # The auto-mint rule, declared. A mint without the owner's confirm runs only when all four hold, and the
3187
+ # mint entry point (`Adapters::MainMaintenance#mint`, checked by `Adapters::QaAutoMint`) enforces it:
3188
+ # (a) the translation edge leaving the held era is empty: no aggregate block, derive, drop, rename,
3189
+ # convert, retype or rekey;
3190
+ # (b) every change in the shape diff is additive: an attribute an existing aggregate gained is optional,
3191
+ # and a new aggregate, required attributes included, adds no field to an existing one;
3192
+ # (c) the rehearsal said would_mint with a refusal total of 0, at the live watermark;
3193
+ # (d) no stranded marker exists.
3194
+ # Otherwise the mint is held: the entry point refuses it as "needs owner approval", and the policy below
3195
+ # asks for the approval, which answers `MintNeedsApproval` and stops. A stale watermark or a stranded
3196
+ # marker is a refusal, never a held mint. The ask forwards no `ledger_dir`: an optional attribute a call
3197
+ # leaves out is not on the event, so the entry point takes the QualityControl ledger by default.
3198
+ policy "AutoMintAdditive" do
3199
+ on "Maintenance.MintRequested"
3200
+ where { rehearsal_verdict.value == "would_mint" }
3201
+ ask :mint, with: { run: :run, domain: :domain, era: :era, sha: :sha, branch: :branch,
3202
+ watermark: :watermark, rehearsal_verdict: :rehearsal_verdict,
3203
+ refusal_total: :refusal_total, confirm: :confirm }
3204
+ end
3205
+
3206
+ # Holds a mint the auto-mint rule does not cover for the owner. Reads the refusal the entry point named.
3207
+ policy "AskOwnerApprovalOnHeldMint" do
3208
+ on "Maintenance.MintRefused"
3209
+ where { refusal && refusal.value.start_with?("needs owner approval") }
3210
+ ask :approval, with: { domain: :domain, era: :era, reason: :refusal }
3211
+ end
3212
+
3213
+ policy "LandOnMinted" do
3214
+ on "Maintenance.Minted"
3215
+ where { branch.value != "" }
3216
+ ask :land, with: { run: :run, era: :era, sha: :sha, branch: :branch }
3217
+ end
3218
+
3219
+ # The release PR chain. A version bump opens its PR; the conditions judged on `ReleaseChecked` either
3220
+ # approve it (every condition `met`) or refuse it by the name of the condition that failed. An approval
3221
+ # writes the release trailer on the merge through the `ReleaseGh` port.
3222
+ policy "OpenOnReleaseRequest" do
3223
+ on "ReleasePR.ReleaseOpenRequested"
3224
+ ask :open_pull_request, with: { release: :release, branch: :branch, sha: :sha }
3225
+ end
3226
+
3227
+ policy "ApproveOnConditionsMet" do
3228
+ on "ReleasePR.ReleaseChecked"
3229
+ where { condition.value == "met" }
3230
+ trigger ReleasePR::Approve, with: { release: :release, sha: :sha, condition: :condition,
3231
+ approver: :approver, trailer: :trailer }
3232
+ end
3233
+
3234
+ policy "RefuseOnFailedCondition" do
3235
+ on "ReleasePR.ReleaseChecked"
3236
+ where { condition.value != "met" }
3237
+ trigger ReleasePR::Refuse, with: { release: :release, condition: :condition }
3238
+ end
3239
+
3240
+ policy "WriteTrailerOnApproved" do
3241
+ on "ReleasePR.ReleaseApproved"
3242
+ ask :write_trailer, with: { approver: :approver, trailer: :trailer }
3243
+ end
3244
+
3245
+ # ---- The push nudge ----------------------------------------------------------------------------
3246
+ # Local main drifting ahead of origin/main is red that nobody sees. Each tick checks once whether a
3247
+ # push is due and keeps ONE Work row, `push-due`, for QA: filed when the push is due beyond the
3248
+ # world's thresholds, updated while it stays due, finished when it no longer is. The check reads
3249
+ # refs git already holds (`PushRehearsal.Due`); it never fetches, pushes or merges. Tickets turns the
3250
+ # answer into the row (`PlanWorkWhenPushDue`, `ReviseWorkWhenPushStillDue`, `FinishWorkWhenPushSettled`).
3251
+ aggregate "PushNudge" do
3252
+ description "One check of whether a push of local main is due: whether it is, whether the push-due Work row is already open, and the numbers."
3253
+
3254
+ identified_by :nudge
3255
+
3256
+ attribute :nudge, NudgeKey
3257
+ attribute :due, NudgeFlag, optional: true
3258
+ attribute :raised, NudgeFlag, optional: true
3259
+ attribute :work, NudgeLine, optional: true
3260
+ attribute :title, NudgeLine, optional: true
3261
+ attribute :detail, NudgeLine, optional: true
3262
+
3263
+ value_object "NudgeKey" do
3264
+ attribute :value, String, matches: :present
3265
+ end
3266
+
3267
+ # "yes" or "no".
3268
+ value_object "NudgeFlag" do
3269
+ attribute :value, String, default: ""
3270
+ end
3271
+
3272
+ value_object "NudgeLine" do
3273
+ attribute :value, String, default: ""
3274
+ end
3275
+
3276
+ command "Check" do
3277
+ role "QA engineer"
3278
+ goal "Ask whether a push of local main is due, from the refs git already holds"
3279
+
3280
+ attribute :nudge, NudgeKey, sets: true
3281
+
3282
+ emits "PushDueCheckRequested"
3283
+ end
3284
+
3285
+ command "Record" do
3286
+ role "System"
3287
+ goal "Keep what a check found"
3288
+
3289
+ reference_to PushNudge
3290
+ attribute :due, NudgeFlag, sets: true
3291
+ attribute :raised, NudgeFlag, sets: true
3292
+ attribute :detail, NudgeLine, sets: true
3293
+
3294
+ emits "PushDueRecorded"
3295
+ end
3296
+ end
3297
+
3298
+ policy "ReadPushDueOnCheck" do
3299
+ on "PushNudge.PushDueCheckRequested"
3300
+ ask :read, with: { nudge: :nudge }
3301
+ end
3302
+
3303
+ policy "RecordThePushDueRead" do
3304
+ on "PushNudge.PushDueRead"
3305
+ trigger PushNudge::Record, with: { due: :due, raised: :raised, detail: :detail }
3306
+ end
2187
3307
  end