hecks 7.0.0 → 7.1.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 (257) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/postgres_era/lineage/chain_sql.rb +2 -1
  3. data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +4 -2
  4. data/lib/hecks/adapters/driven/postgres_era/lineage/split_sql.rb +16 -8
  5. data/lib/hecks/adapters/driven/postgres_era/lineage/transform_sql.rb +7 -3
  6. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +2 -1
  7. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/mint_request.rb +2 -1
  8. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/refusals.rb +2 -1
  9. data/lib/hecks/adapters/driving/cli_runner/bang_rule.rb +3 -0
  10. data/lib/hecks/adapters/driving/cli_runner/completion_words.rb +2 -0
  11. data/lib/hecks/adapters/driving/cli_runner/read_context.rb +6 -3
  12. data/lib/hecks/adapters/driving/cli_runner/renamed_names.rb +2 -1
  13. data/lib/hecks/adapters/driving/cli_runner/resolution.rb +2 -2
  14. data/lib/hecks/adapters/driving/cli_runner/resume_words.rb +1 -0
  15. data/lib/hecks/adapters/driving/cli_runner/run_reference.rb +6 -3
  16. data/lib/hecks/adapters/driving/cli_runner/search_words.rb +2 -0
  17. data/lib/hecks/adapters/driving/cli_runner/tour_words.rb +1 -0
  18. data/lib/hecks/adapters/driving/cli_runner/verb_names.rb +2 -1
  19. data/lib/hecks/adapters/driving/cli_runner/verbosity.rb +2 -0
  20. data/lib/hecks/adapters/driving/cli_runner/word_help.rb +40 -0
  21. data/lib/hecks/adapters/driving/cli_runner.rb +2 -0
  22. data/lib/hecks/adapters/driving/mcp/progress_sink.rb +4 -2
  23. data/lib/hecks/adapters/driving/mcp.rb +2 -1
  24. data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +2 -1
  25. data/lib/hecks/adapters/driving/ruby/aggregate_module/hooks.rb +28 -14
  26. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +4 -2
  27. data/lib/hecks/assembly.rb +18 -4
  28. data/lib/hecks/behaviors/expectations/adapter_selection.rb +82 -0
  29. data/lib/hecks/behaviors/expectations/boot.rb +12 -5
  30. data/lib/hecks/bluebook/acknowledgements.rb +1 -1
  31. data/lib/hecks/bluebook/command.rb +3 -2
  32. data/lib/hecks/bluebook/declaration.rb +2 -1
  33. data/lib/hecks/bluebook/dsl/adapter_builder.rb +9 -1
  34. data/lib/hecks/bluebook/dsl/bluebook_builder/metadata.rb +6 -4
  35. data/lib/hecks/bluebook/dsl/bluebook_builder/modules.rb +6 -3
  36. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/correlation_keys.rb +2 -1
  37. data/lib/hecks/bluebook/dsl/command_builder/folded_sets.rb +4 -2
  38. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +2 -1
  39. data/lib/hecks/bluebook/hecksagon.rb +6 -3
  40. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +9 -2
  41. data/lib/hecks/bluebook/meta_validator.rb +1 -1
  42. data/lib/hecks/bluebook/model_check/aggregate_checks.rb +2 -1
  43. data/lib/hecks/bluebook/model_check/classification_checks.rb +51 -0
  44. data/lib/hecks/bluebook/model_check/context_checks.rb +2 -0
  45. data/lib/hecks/bluebook/model_check/redundant_relationships.rb +2 -1
  46. data/lib/hecks/ci_speed/adapters/shard_partitioner.adapter +7 -0
  47. data/lib/hecks/ci_speed/adapters/shard_partitioner.rb +66 -0
  48. data/lib/hecks/ci_speed/adapters/timings_source.adapter +7 -0
  49. data/lib/hecks/ci_speed/adapters/timings_source.rb +68 -0
  50. data/lib/hecks/ci_speed/ci_speed.bluebook +111 -0
  51. data/lib/hecks/ci_speed/ci_speed.ports.hecksagon +22 -0
  52. data/lib/hecks/ci_workflows/ci_workflows.bluebook +50 -6
  53. data/lib/hecks/coder/coder.bluebook +3 -1
  54. data/lib/hecks/command_names/index.rb +1 -1
  55. data/lib/hecks/command_names/resolution.rb +15 -5
  56. data/lib/hecks/composer/toolbox.rb +2 -1
  57. data/lib/hecks/corpus.rb +4 -0
  58. data/lib/hecks/doc/reference/readme.rb +1 -1
  59. data/lib/hecks/framework_bluebooks.rb +3 -2
  60. data/lib/hecks/fuzzing/differential.rb +1 -1
  61. data/lib/hecks/fuzzing/era_boundary.rb +1 -1
  62. data/lib/hecks/fuzzing/isolated_boot/postgres_scratch.rb +1 -1
  63. data/lib/hecks/fuzzing/persistence_parity.rb +1 -1
  64. data/lib/hecks/fuzzing/target_capabilities.rb +1 -1
  65. data/lib/hecks/hecks/adapters/ci_runs.adapter +7 -0
  66. data/lib/hecks/hecks/adapters/ci_runs.rb +80 -0
  67. data/lib/hecks/hecks/adapters/claude_agent_list.rb +43 -0
  68. data/lib/hecks/hecks/adapters/claude_agents.rb +50 -19
  69. data/lib/hecks/hecks/adapters/claude_jobs.rb +36 -0
  70. data/lib/hecks/hecks/adapters/codebase/corpus_queries.rb +2 -1
  71. data/lib/hecks/hecks/adapters/codebase/minitest_runs.rb +4 -2
  72. data/lib/hecks/hecks/adapters/codebase/run_options.rb +2 -1
  73. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +3 -19
  74. data/lib/hecks/hecks/adapters/dispatching/brief_text.rb +5 -3
  75. data/lib/hecks/hecks/adapters/dispatching/launcher.rb +2 -1
  76. data/lib/hecks/hecks/adapters/dispatching/plan.rb +8 -4
  77. data/lib/hecks/hecks/adapters/dispatching/settings.rb +2 -1
  78. data/lib/hecks/hecks/adapters/dispatching/settler.rb +4 -2
  79. data/lib/hecks/hecks/adapters/dispatching.rb +6 -3
  80. data/lib/hecks/hecks/adapters/doctor_reading.rb +4 -2
  81. data/lib/hecks/hecks/adapters/git_landing/carried.rb +42 -0
  82. data/lib/hecks/hecks/adapters/git_landing/finisher.rb +2 -1
  83. data/lib/hecks/hecks/adapters/git_landing/flagged.rb +32 -0
  84. data/lib/hecks/hecks/adapters/git_landing/tidy.rb +27 -14
  85. data/lib/hecks/hecks/adapters/git_landing.rb +30 -13
  86. data/lib/hecks/hecks/adapters/git_leftovers.adapter +7 -0
  87. data/lib/hecks/hecks/adapters/git_leftovers.rb +49 -0
  88. data/lib/hecks/hecks/adapters/git_main_pull.rb +2 -2
  89. data/lib/hecks/hecks/adapters/git_train.rb +9 -5
  90. data/lib/hecks/hecks/adapters/git_worktree_add.rb +8 -4
  91. data/lib/hecks/hecks/adapters/github_pull_requests.rb +2 -1
  92. data/lib/hecks/hecks/adapters/in_process_operations.rb +2 -1
  93. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +1 -1
  94. data/lib/hecks/hecks/adapters/journal_store/readings/composition.rb +2 -1
  95. data/lib/hecks/hecks/adapters/journal_store/translation_write/shape_edge.rb +4 -2
  96. data/lib/hecks/hecks/adapters/journal_store/translation_write.rb +4 -2
  97. data/lib/hecks/hecks/adapters/landed_branches.rb +38 -0
  98. data/lib/hecks/hecks/adapters/main_boarding.adapter +7 -0
  99. data/lib/hecks/hecks/adapters/main_boarding.rb +85 -0
  100. data/lib/hecks/hecks/adapters/main_integration/checks.rb +63 -0
  101. data/lib/hecks/hecks/adapters/main_integration/command_runner.rb +32 -0
  102. data/lib/hecks/hecks/adapters/main_integration/range_guard.rb +49 -0
  103. data/lib/hecks/hecks/adapters/main_integration/repository.rb +83 -0
  104. data/lib/hecks/hecks/adapters/main_integration/runs.rb +51 -0
  105. data/lib/hecks/hecks/adapters/main_integration/train.rb +74 -0
  106. data/lib/hecks/hecks/adapters/main_integration.adapter +7 -0
  107. data/lib/hecks/hecks/adapters/main_integration.rb +77 -0
  108. data/lib/hecks/hecks/adapters/main_verification.adapter +7 -0
  109. data/lib/hecks/hecks/adapters/main_verification.rb +89 -0
  110. data/lib/hecks/hecks/adapters/push_recorder.adapter +7 -0
  111. data/lib/hecks/hecks/adapters/push_recorder.rb +78 -0
  112. data/lib/hecks/hecks/adapters/red_flag_guard.rb +62 -0
  113. data/lib/hecks/hecks/adapters/red_flag_marker.rb +101 -0
  114. data/lib/hecks/hecks/adapters/red_flag_report.rb +59 -0
  115. data/lib/hecks/hecks/adapters/red_flag_survey.rb +65 -0
  116. data/lib/hecks/hecks/adapters/red_flagging.adapter +7 -0
  117. data/lib/hecks/hecks/adapters/red_flagging.rb +98 -0
  118. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +6 -1
  119. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +6 -3
  120. data/lib/hecks/hecks/adapters/settings_reading/event_tap_row.rb +33 -0
  121. data/lib/hecks/hecks/adapters/settings_reading.rb +3 -1
  122. data/lib/hecks/hecks/codebase.behaviors +0 -6
  123. data/lib/hecks/hecks/custodian.behaviors +22 -1
  124. data/lib/hecks/hecks/delegate/delegate.bluebook +128 -15
  125. data/lib/hecks/hecks/deliver/deliver.bluebook +450 -2
  126. data/lib/hecks/hecks/environments/memory.world +5 -0
  127. data/lib/hecks/hecks/hecks.contextmap +8 -0
  128. data/lib/hecks/hecks/hecks.hecksagon +106 -6
  129. data/lib/hecks/hecks/hecks.world +9 -1
  130. data/lib/hecks/hecks/migrate/migrate.bluebook +6 -1
  131. data/lib/hecks/hecks/redflag/redflag.bluebook +249 -0
  132. data/lib/hecks/hecks/test/test.bluebook +0 -19
  133. data/lib/hecks/language/adapter.bluebook +13 -0
  134. data/lib/hecks/language/bluebook/vocabulary.bluebook +8 -9
  135. data/lib/hecks/language/sentence/sentence.bluebook +2 -0
  136. data/lib/hecks/pipeline/pipeline.bluebook +251 -0
  137. data/lib/hecks/pipeline/pipeline.hecksagon +17 -0
  138. data/lib/hecks/pipeline_board/adapters/cache.rb +43 -0
  139. data/lib/hecks/pipeline_board/adapters/pipeline_fill.rb +56 -0
  140. data/lib/hecks/pipeline_board/adapters/pipeline_git.rb +82 -0
  141. data/lib/hecks/pipeline_board/adapters/pipeline_github/runs.rb +66 -0
  142. data/lib/hecks/pipeline_board/adapters/pipeline_github.adapter +7 -0
  143. data/lib/hecks/pipeline_board/adapters/pipeline_github.rb +70 -0
  144. data/lib/hecks/pipeline_board/adapters/pipeline_jobs.adapter +7 -0
  145. data/lib/hecks/pipeline_board/adapters/pipeline_jobs.rb +87 -0
  146. data/lib/hecks/pipeline_board/adapters/pipeline_journal/chain.rb +40 -0
  147. data/lib/hecks/pipeline_board/adapters/pipeline_journal/tap.rb +75 -0
  148. data/lib/hecks/pipeline_board/adapters/pipeline_journal.adapter +7 -0
  149. data/lib/hecks/pipeline_board/adapters/pipeline_journal.rb +83 -0
  150. data/lib/hecks/pipeline_board/adapters/pipeline_stages/ci_tiles.rb +85 -0
  151. data/lib/hecks/pipeline_board/adapters/pipeline_stages/fanout.rb +73 -0
  152. data/lib/hecks/pipeline_board/adapters/pipeline_stages/gather.rb +57 -0
  153. data/lib/hecks/pipeline_board/adapters/pipeline_stages/metrics.rb +36 -0
  154. data/lib/hecks/pipeline_board/adapters/pipeline_stages/strip.rb +102 -0
  155. data/lib/hecks/pipeline_board/adapters/pipeline_stages/tile_kit.rb +57 -0
  156. data/lib/hecks/pipeline_board/adapters/pipeline_stages/work_tiles.rb +59 -0
  157. data/lib/hecks/pipeline_board/adapters/pipeline_stages.adapter +7 -0
  158. data/lib/hecks/pipeline_board/adapters/pipeline_stages.rb +84 -0
  159. data/lib/hecks/pipeline_board/adapters/pipeline_tickets.adapter +7 -0
  160. data/lib/hecks/pipeline_board/adapters/pipeline_tickets.rb +77 -0
  161. data/lib/hecks/pipeline_board/adapters/pipeline_web/page.html +292 -0
  162. data/lib/hecks/pipeline_board/adapters/pipeline_web/sequence.html +190 -0
  163. data/lib/hecks/pipeline_board/adapters/pipeline_web/server.rb +105 -0
  164. data/lib/hecks/pipeline_board/adapters/pipeline_web/snapshot.rb +57 -0
  165. data/lib/hecks/pipeline_board/adapters/pipeline_web/stream.rb +59 -0
  166. data/lib/hecks/pipeline_board/adapters/pipeline_web/wiring.html +536 -0
  167. data/lib/hecks/pipeline_board/adapters/pipeline_web.adapter +7 -0
  168. data/lib/hecks/pipeline_board/adapters/pipeline_web.rb +80 -0
  169. data/lib/hecks/pipeline_board/adapters/pipeline_wiring/details.rb +85 -0
  170. data/lib/hecks/pipeline_board/adapters/pipeline_wiring/graph.rb +120 -0
  171. data/lib/hecks/pipeline_board/adapters/pipeline_wiring.adapter +7 -0
  172. data/lib/hecks/pipeline_board/adapters/pipeline_wiring.rb +36 -0
  173. data/lib/hecks/pipeline_board/adapters/probe.rb +48 -0
  174. data/lib/hecks/pipeline_board/pipeline_board.bluebook +144 -0
  175. data/lib/hecks/pipeline_board/pipeline_board.hecksagon +12 -0
  176. data/lib/hecks/pipeline_board/pipeline_board.ports.hecksagon +47 -0
  177. data/lib/hecks/ports/persistence/binding_policy.rb +2 -1
  178. data/lib/hecks/ports/persistence/plugins/era/translation/compose.rb +4 -3
  179. data/lib/hecks/ports/persistence/repository_factory.rb +2 -1
  180. data/lib/hecks/projections/ci_pipeline/table.rb +2 -1
  181. data/lib/hecks/projections/deploy/lambda/stack/recipes.rb +2 -2
  182. data/lib/hecks/projections/undo.rb +2 -1
  183. data/lib/hecks/projector/cli_projector/command_help.rb +5 -4
  184. data/lib/hecks/projector/cli_projector/renames.rb +4 -2
  185. data/lib/hecks/projector/cli_projector/usage.rb +4 -3
  186. data/lib/hecks/projector/exporter/adapters.rb +3 -2
  187. data/lib/hecks/projector/narrate_projector/use_cases.rb +74 -0
  188. data/lib/hecks/projector/narrate_projector.rb +10 -3
  189. data/lib/hecks/quality_control/adapters/main_maintenance.rb +9 -5
  190. data/lib/hecks/quality_control/adapters/qa_auto_mint.rb +21 -2
  191. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +1 -1
  192. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +2 -1
  193. data/lib/hecks/quality_control/cli/qa_fix_main_bug/publishing.rb +8 -4
  194. data/lib/hecks/quality_control/cli/qa_fix_main_bug.rb +10 -8
  195. data/lib/hecks/quality_control/cli/qa_generated_domains/promotion.rb +2 -2
  196. data/lib/hecks/quality_control/cli/qa_main_gate/gate_run.rb +6 -3
  197. data/lib/hecks/quality_control/cli/qa_main_gate/logging.rb +8 -4
  198. data/lib/hecks/quality_control/cli/qa_main_gate/shell.rb +4 -2
  199. data/lib/hecks/quality_control/cli/qa_main_gate/sweeping.rb +8 -4
  200. data/lib/hecks/quality_control/cli/qa_main_gate/worktree.rb +3 -2
  201. data/lib/hecks/quality_control/cli/qa_main_gate.rb +10 -5
  202. data/lib/hecks/quality_control/cli/qa_sweep/all_mode/children.rb +1 -1
  203. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +1 -1
  204. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  205. data/lib/hecks/quality_control/cli/qa_tick.rb +6 -3
  206. data/lib/hecks/quality_control/quality_control.bluebook +11 -11
  207. data/lib/hecks/quality_control/quality_control.ports.hecksagon +6 -3
  208. data/lib/hecks/query_ir/touchpoints.rb +2 -1
  209. data/lib/hecks/refused.rb +2 -1
  210. data/lib/hecks/release/approval.rb +4 -2
  211. data/lib/hecks/runtime/event_log.rb +27 -0
  212. data/lib/hecks/runtime/event_tap.rb +106 -0
  213. data/lib/hecks/runtime/loader/boot_steps.rb +1 -1
  214. data/lib/hecks/runtime/loader.rb +35 -19
  215. data/lib/hecks/runtime/registry/durability_warnings.rb +12 -5
  216. data/lib/hecks/runtime/registry/runtime_state.rb +4 -1
  217. data/lib/hecks/runtime/registry/saga_anchor.rb +54 -0
  218. data/lib/hecks/runtime/registry/saga_durability_rule.rb +66 -0
  219. data/lib/hecks/runtime/registry/saga_persistence.rb +58 -12
  220. data/lib/hecks/runtime/registry/verification.rb +7 -3
  221. data/lib/hecks/runtime/saga_interpreter/lifecycle.rb +2 -1
  222. data/lib/hecks/runtime/saga_interpreter.rb +1 -1
  223. data/lib/hecks/rust_format.rb +2 -1
  224. data/lib/hecks/shape_ledger/edge_hygiene.rb +10 -5
  225. data/lib/hecks/shape_ledger.rb +1 -1
  226. data/lib/hecks/storehouse/audit.rb +2 -1
  227. data/lib/hecks/storehouse/identity.rb +6 -3
  228. data/lib/hecks/storehouse.rb +2 -1
  229. data/lib/hecks/tickets/bluebook/tickets.bluebook +5 -4
  230. data/lib/hecks/tools/ci_workflows.rb +2 -1
  231. data/lib/hecks/tools/document.rb +12 -1
  232. data/lib/hecks/tools/downstream_model_check.rb +4 -2
  233. data/lib/hecks/tools/fuzz_sweep/shards.rb +9 -30
  234. data/lib/hecks/tools/model_check/examination.rb +25 -2
  235. data/lib/hecks/tools/move_disables.rb +4 -2
  236. data/lib/hecks/tools/regeneration_run/scratch.rb +2 -1
  237. data/lib/hecks/tools/rspec_shard_files.rb +12 -15
  238. data/lib/hecks/tools/sequence_script.rb +1 -1
  239. data/lib/hecks/tools/shard_planner.rb +65 -0
  240. data/lib/hecks/tools/stage_progress.rb +2 -1
  241. data/lib/hecks/tools/stress_concurrency_specs.rb +2 -1
  242. data/lib/hecks/version.rb +1 -1
  243. data/lib/hecks/vocabulary.rb +8 -9
  244. data/lib/hecks.rb +5 -2
  245. data/prebuilt/{13c04bdc5970295b310f0a980d397ba722232c8da99cc1a0cdb383249921e871.marshal → 4b81646f769ae5b1e7457f9b11c48d8bc1093e96a1dd6fb61864065121ca6f01.marshal} +0 -0
  246. data/prebuilt/{e3857b77f47d9ecc1787b2e1f5136364f3cb3444ef4aea5479f3b98167affea2.marshal → 681890632e3f4a99646623dcae44af36b1bad66c515f5abf67a2460372b9c6fd.marshal} +0 -0
  247. data/rust/host/HECKS_RELEASE +1 -1
  248. data/rust/parser/src/emit.rs +5 -1
  249. data/rust/parser/src/ir.rs +2 -0
  250. data/rust/parser/src/keywords.rs +12 -0
  251. data/rust/parser/src/main.rs +1 -0
  252. data/rust/parser/src/parse/adapter.rs +1 -0
  253. data/rust/parser/src/phrases.rs +16 -0
  254. data/rust/parser/src/sentence/examples.rs +93 -0
  255. data/rust/parser/src/sentence/mod.rs +1 -0
  256. metadata +89 -5
  257. data/lib/hecks/tools/refresh_rspec_runtime_baseline.rb +0 -166
@@ -342,6 +342,7 @@ Hecks.bluebook "Hecks" do
342
342
  attribute :onto, Word, optional: true
343
343
  attribute :from, RunKey, optional: true
344
344
  attribute :landed, Word, optional: true
345
+ attribute :reason, Report, optional: true
345
346
  attribute :report, Report, optional: true
346
347
  attribute :refusal, Report, optional: true
347
348
  identified_by :run
@@ -367,10 +368,12 @@ Hecks.bluebook "Hecks" do
367
368
  mark :failure, "refused"
368
369
  transition "Record" => "landed", from: "requested"
369
370
  transition "Clear" => "retired", from: "requested"
371
+ transition "Dispose" => "discarded", from: "requested"
372
+ transition "Spare" => "refused", from: "requested"
370
373
  transition "Refuse" => "refused", from: "requested"
371
374
  transition "Decline" => "refused", from: "requested"
372
375
  transition "Convoy" => "convoyed", from: "requested"
373
- mark :terminal, "landed", "refused", "retired", "convoyed"
376
+ mark :terminal, "landed", "refused", "retired", "discarded", "convoyed"
374
377
  end
375
378
 
376
379
  command "Land" do
@@ -467,6 +470,44 @@ Hecks.bluebook "Hecks" do
467
470
  emits RetirementRequested
468
471
  end
469
472
 
473
+ command "Discard" do
474
+ role "Operator"
475
+ goal "Remove a worktree and delete its branch even though main lacks its commits, for a stated reason: refused for a protected branch, a worktree in use, or uncommitted work"
476
+
477
+ attribute :run, RunKey, sets: true
478
+ attribute :checkout, Word, optional: true, sets: true
479
+ attribute :branch, Word, optional: true, sets: true
480
+ attribute :onto, Word, default: "main", sets: true
481
+ attribute :reason, Report, sets: true
482
+ attribute :confirm, Switch, optional: true, sets: true
483
+
484
+ given("a discard says why") { reason.value != "" }
485
+ given("discards the branch's commits that main lacks needs --confirm; without it this only reports") { confirm.value == true }
486
+
487
+ emits DiscardRequested
488
+ end
489
+
490
+ command "Dispose" do
491
+ role "System"
492
+ goal "Record that the worktree and its branch were discarded, with the tip they were at"
493
+
494
+ reference_to Landing
495
+ attribute :branch, Word, sets: true
496
+ attribute :report, Report, sets: true
497
+
498
+ emits WorktreeDiscarded
499
+ end
500
+
501
+ command "Spare" do
502
+ role "System"
503
+ goal "Record why a worktree was not discarded"
504
+
505
+ reference_to Landing
506
+ attribute :refusal, Report, sets: true
507
+
508
+ emits DiscardDeclined
509
+ end
510
+
470
511
  command "Clear" do
471
512
  role "System"
472
513
  goal "Record that the worktree and its branch are gone"
@@ -554,6 +595,21 @@ Hecks.bluebook "Hecks" do
554
595
  ask :remove, with: { run: :run }
555
596
  end
556
597
 
598
+ policy "DiscardWhenAsked" do
599
+ on "Landing.DiscardRequested"
600
+ ask :drop_branch, with: { run: :run }
601
+ end
602
+
603
+ policy "RecordTheDiscard" do
604
+ on "Landing.DiscardAnswered"
605
+ trigger Landing::Dispose, with: { branch: :branch, report: :report }
606
+ end
607
+
608
+ policy "RecordTheSparedWorktree" do
609
+ on "Landing.DiscardRefused"
610
+ trigger Landing::Spare, with: { refusal: :refusal }
611
+ end
612
+
557
613
  policy "RecordTheRetirement" do
558
614
  on "Landing.RemovalAnswered"
559
615
  trigger Landing::Clear, with: { branch: :branch, report: :report }
@@ -602,6 +658,7 @@ Hecks.bluebook "Hecks" do
602
658
  attribute :full_gate, Switch, optional: true
603
659
  attribute :boarded, Word, optional: true
604
660
  attribute :pushed, Word, optional: true
661
+ attribute :commits, Count, optional: true
605
662
  attribute :report, Report, optional: true
606
663
  attribute :refusal, Report, optional: true
607
664
  identified_by :run
@@ -623,6 +680,12 @@ Hecks.bluebook "Hecks" do
623
680
  attribute :value, Boolean
624
681
  end
625
682
 
683
+ # How many commits the branch held that the remote did not, as the boarding began.
684
+ value_object "Count" do
685
+ attribute :value, Integer
686
+ invariant("a count is not negative") { !value.negative? }
687
+ end
688
+
626
689
  lifecycle :status, default: "requested" do
627
690
  mark :failure, "faulted"
628
691
  transition "Send" => "pushed", from: "requested"
@@ -685,6 +748,7 @@ Hecks.bluebook "Hecks" do
685
748
  attribute :checkout, Word, sets: true
686
749
  attribute :boarded, Word, sets: true
687
750
  attribute :pushed, Word, sets: true
751
+ attribute :commits, Count, optional: true, sets: true
688
752
  attribute :report, Report, sets: true
689
753
 
690
754
 
@@ -735,7 +799,8 @@ Hecks.bluebook "Hecks" do
735
799
  policy "RecordThePush" do
736
800
  on "SendTrain.TrainAnswered"
737
801
  where { outcome.value == "pushed" }
738
- trigger SendTrain::Send, with: { checkout: :checkout, boarded: :boarded, pushed: :pushed, report: :report }
802
+ trigger SendTrain::Send, with: { checkout: :checkout, boarded: :boarded, pushed: :pushed, commits: :commits,
803
+ report: :report }
739
804
  end
740
805
 
741
806
  policy "RecordTheRide" do
@@ -771,6 +836,86 @@ Hecks.bluebook "Hecks" do
771
836
  ask :announce, with: { run: :run, pushed: :pushed }
772
837
  end
773
838
 
839
+ # What landings left behind is listed after a push, and nothing is removed: a session may still
840
+ # be working in a worktree whose branch landed, and a clean tree looks the same as a finished one.
841
+ policy "ListLeftoversWhenPushed" do
842
+ on "SendTrain.BranchPushed"
843
+ ask :leftovers, with: { run: :run, pushed: :pushed }
844
+ end
845
+
846
+ # The train runs in Memory, in a checkout of its own, so its outcome is recorded where the
847
+ # boarded checkout keeps its records: the `PushRecords` port runs that checkout's own
848
+ # `PushOutcome.Record`. A recording that fails is answered `OutcomeUnrecorded` and changes
849
+ # nothing about the push.
850
+ policy "RecordThePushedOutcome" do
851
+ on "SendTrain.BranchPushed"
852
+ ask :record_outcome, with: { run: :run }
853
+ end
854
+
855
+ policy "RecordTheCarriedOutcome" do
856
+ on "SendTrain.CarriedByEarlierPush"
857
+ ask :record_outcome, with: { run: :run }
858
+ end
859
+
860
+ policy "RecordTheFaultedOutcome" do
861
+ on "SendTrain.PushFaulted"
862
+ ask :record_outcome, with: { run: :run }
863
+ end
864
+
865
+ # How one boarding of the train ended, recorded by the checkout that boarded it. It is its own
866
+ # aggregate, not SendTrain, so recording a push in the checkout fires none of the reactions a
867
+ # push itself has (the launcher refresh, the deploy announcement, the GateAndBoard saga).
868
+ aggregate "PushOutcome" do
869
+ description "How one boarding of the push train ended, as the boarded checkout records it: pushed, carried or faulted."
870
+
871
+ attribute :run, OutcomeKey
872
+ attribute :checkout, Locator
873
+ attribute :branch, Locator, optional: true
874
+ attribute :outcome, Ending
875
+ attribute :pushed, Locator, optional: true
876
+ attribute :commits, Tally, optional: true
877
+ attribute :report, Line, optional: true
878
+ identified_by :run
879
+
880
+ # The boarding's run and how it ended, so a boarding run again is recorded beside the first.
881
+ value_object "OutcomeKey" do
882
+ attribute :value, String, matches: :present
883
+ end
884
+
885
+ # A checkout (written with its trailing slash), a branch or a commit.
886
+ value_object "Locator" do
887
+ attribute :value, String, matches: :present
888
+ end
889
+
890
+ value_object "Ending" do
891
+ attribute :value, String, pattern: '\A(pushed|carried|faulted)\z'
892
+ end
893
+
894
+ value_object "Tally" do
895
+ attribute :value, Integer
896
+ invariant("a count is not negative") { !value.negative? }
897
+ end
898
+
899
+ value_object "Line" do
900
+ attribute :value, String
901
+ end
902
+
903
+ command "Record" do
904
+ role "Operator"
905
+ goal "Record how one boarding of the push train ended, in the checkout that boarded it"
906
+
907
+ attribute :run, OutcomeKey, sets: true
908
+ attribute :checkout, Locator, sets: true
909
+ attribute :branch, Locator, optional: true, sets: true
910
+ attribute :outcome, Ending, sets: true
911
+ attribute :pushed, Locator, optional: true, sets: true
912
+ attribute :commits, Tally, optional: true, sets: true
913
+ attribute :report, Line, optional: true, sets: true
914
+
915
+ emits PushRecorded
916
+ end
917
+ end
918
+
774
919
  # The request that starts GateAndBoard, under its own identity so the Landing record it leads to
775
920
  # is a separate one: Land creates a Landing under the same run key, and that would collide.
776
921
  aggregate "Shipment" do
@@ -807,6 +952,309 @@ Hecks.bluebook "Hecks" do
807
952
  end
808
953
  end
809
954
 
955
+ # Main is integrated by a process: every landing onto local main starts a run keyed by the
956
+ # landed commit, and each run is verified in a clean copy, boarded on the push train and
957
+ # watched on CI, ending green or red, or parked in needs_human with the reason. The
958
+ # coordinator drives it with `Integration.advance!`, which dispatches each open run's next step
959
+ # at top level; a step records itself and waits, so no dispatch runs inside the saga and the
960
+ # reaction depth stays bounded. Shipment's path joins it: its landing starts a run too, and a
961
+ # boarding the train already carried is recorded as pushed. A run is checkpointed with the
962
+ # Landing records that start it, so a copy that keeps those keeps its runs across a restart.
963
+ # A run in needs_human is taken up again by verifying it again (`Integration.verify!`).
964
+ process_manager "MainIntegration" do
965
+ correlates_by :"landed.value"
966
+ starts_on Landing::BranchLanded
967
+
968
+ transition Integration::MainVerificationStarted => "verifying", from: %w[landed needs_human]
969
+ transition Integration::MainVerified => "verified", from: "verifying"
970
+ transition Integration::MainBoardingStarted => "boarding", from: "verified"
971
+ transition Integration::MainPushed => "pushed", from: "boarding"
972
+ transition Integration::CiObservationStarted => "ci_running", from: %w[pushed ci_running]
973
+ transition Integration::CiPassed => "green", from: "ci_running"
974
+ transition Integration::CiFailed => "red", from: "ci_running"
975
+
976
+ # A newer landing on main carries this one: the run stops, and the newer run integrates both.
977
+ transition Integration::IntegrationSuperseded => "superseded", from: %w[verifying boarding]
978
+
979
+ transition Integration::MainVerificationFailed => "needs_human", from: "verifying"
980
+ transition Integration::MainPushRefused => "needs_human", from: "boarding"
981
+ end
982
+
983
+ # One step of integrating main, or one advance of every open run: what was asked, and how it
984
+ # ended. A step names the landed commit its run is keyed by, and every event it emits carries
985
+ # it, so the MainIntegration saga hears each one. Each step emits the event that moves the saga
986
+ # before the one its adapter answers, because policies hear an event before sagas do. The port
987
+ # adapters do the work: a clean detached copy for a verification, the push train's own copy for
988
+ # a boarding, and GitHub for the CI run. A boarding refuses by name a range that carries an
989
+ # agent's trailer, a version change or a release approval, and boards only while no other run is
990
+ # being pushed or watched.
991
+ aggregate "Integration" do
992
+ description "One step of integrating main (verify, board, observe CI) or one advance of the open runs, and how it ended."
993
+
994
+ attribute :run, RunKey
995
+ attribute :landed, Word, optional: true
996
+ attribute :checkout, Word, optional: true
997
+ attribute :confirm, Switch, optional: true
998
+ attribute :pushed, Word, optional: true
999
+ attribute :report, Report, optional: true
1000
+ attribute :refusal, Report, optional: true
1001
+ identified_by :run
1002
+
1003
+ value_object "RunKey" do
1004
+ attribute :value, String, matches: :present
1005
+ end
1006
+
1007
+ # A commit or a directory.
1008
+ value_object "Word" do
1009
+ attribute :value, String, matches: :present
1010
+ end
1011
+
1012
+ value_object "Report" do
1013
+ attribute :value, String
1014
+ end
1015
+
1016
+ value_object "Switch" do
1017
+ attribute :value, Boolean
1018
+ end
1019
+
1020
+ lifecycle :status, default: "requested" do
1021
+ mark :failure, "failed", "refused", "red"
1022
+ transition "Summarize" => "advanced", from: "requested"
1023
+ transition "Pass" => "verified", from: "requested"
1024
+ transition "Fail" => "failed", from: "requested"
1025
+ transition "Send" => "pushed", from: "requested"
1026
+ transition "Reject" => "refused", from: "requested"
1027
+ transition "Green" => "passed", from: "requested"
1028
+ transition "Red" => "red", from: "requested"
1029
+ transition "Supersede" => "superseded", from: "requested"
1030
+ mark :terminal, "advanced", "verified", "failed", "pushed", "refused", "passed", "red", "superseded"
1031
+ end
1032
+
1033
+ command "Advance" do
1034
+ role "Operator"
1035
+ goal "Dispatch the next step of every open integration run, once: verify a landed run, board a verified one, observe a pushed one"
1036
+
1037
+ attribute :run, RunKey, sets: true
1038
+ # Boarding pushes main, so an advance boards only when confirmed; unconfirmed, it says
1039
+ # which boarding it would make.
1040
+ attribute :confirm, Switch, optional: true, sets: true
1041
+
1042
+ emits AdvanceRequested
1043
+ end
1044
+
1045
+ command "Summarize" do
1046
+ role "System"
1047
+ goal "Record what one advance dispatched for each open run"
1048
+
1049
+ reference_to Integration
1050
+ attribute :report, Report, sets: true
1051
+
1052
+ emits IntegrationAdvanced
1053
+ end
1054
+
1055
+ command "Verify" do
1056
+ role "Operator"
1057
+ goal "Verify a landed commit in a clean detached copy of local main: the quick gate, the specs its changes touch, the command names, the CI pipeline and the generated corpus"
1058
+
1059
+ attribute :run, RunKey, sets: true
1060
+ attribute :landed, Word, sets: true
1061
+ attribute :checkout, Word, optional: true, sets: true
1062
+
1063
+ emits MainVerificationStarted
1064
+ emits MainVerificationRequested
1065
+ end
1066
+
1067
+ command "Pass" do
1068
+ role "System"
1069
+ goal "Record that a landed commit passed its verification"
1070
+
1071
+ reference_to Integration
1072
+ attribute :landed, Word, sets: true
1073
+ attribute :report, Report, sets: true
1074
+
1075
+ emits MainVerified
1076
+ end
1077
+
1078
+ command "Fail" do
1079
+ role "System"
1080
+ goal "Record why a landed commit failed its verification, naming the failing checks and files"
1081
+
1082
+ reference_to Integration
1083
+ attribute :landed, Word, sets: true
1084
+ attribute :refusal, Report, sets: true
1085
+
1086
+ emits MainVerificationFailed
1087
+ end
1088
+
1089
+ command "Board" do
1090
+ role "Operator"
1091
+ goal "Push a verified commit of main by boarding the push train in its own copy, refusing an agent's trailer, a version change or a release approval"
1092
+
1093
+ attribute :run, RunKey, sets: true
1094
+ attribute :landed, Word, sets: true
1095
+ attribute :checkout, Word, optional: true, sets: true
1096
+ attribute :confirm, Switch, optional: true, sets: true
1097
+
1098
+ given("pushes main to the remote needs --confirm; without it this only reports") { confirm.value == true }
1099
+
1100
+ emits MainBoardingStarted
1101
+ emits MainBoardingRequested
1102
+ end
1103
+
1104
+ command "Send" do
1105
+ role "System"
1106
+ goal "Record the commit the push train pushed, or found already carried"
1107
+
1108
+ reference_to Integration
1109
+ attribute :landed, Word, sets: true
1110
+ attribute :pushed, Word, sets: true
1111
+ attribute :report, Report, sets: true
1112
+
1113
+ emits MainPushed
1114
+ end
1115
+
1116
+ command "Reject" do
1117
+ role "System"
1118
+ goal "Record why a verified commit was not pushed"
1119
+
1120
+ reference_to Integration
1121
+ attribute :landed, Word, sets: true
1122
+ attribute :refusal, Report, sets: true
1123
+
1124
+ emits MainPushRefused
1125
+ end
1126
+
1127
+ command "Observe" do
1128
+ role "Operator"
1129
+ goal "Read the CI run of a pushed commit on GitHub: passed, failed with the failed jobs, or still running"
1130
+
1131
+ attribute :run, RunKey, sets: true
1132
+ attribute :landed, Word, sets: true
1133
+ attribute :checkout, Word, optional: true, sets: true
1134
+
1135
+ emits CiObservationStarted
1136
+ emits CiObservationRequested
1137
+ end
1138
+
1139
+ command "Green" do
1140
+ role "System"
1141
+ goal "Record that CI passed on a pushed commit"
1142
+
1143
+ reference_to Integration
1144
+ attribute :landed, Word, sets: true
1145
+ attribute :report, Report, sets: true
1146
+
1147
+ emits CiPassed
1148
+ end
1149
+
1150
+ command "Red" do
1151
+ role "System"
1152
+ goal "Record that CI failed on a pushed commit, naming the failed jobs"
1153
+
1154
+ reference_to Integration
1155
+ attribute :landed, Word, sets: true
1156
+ attribute :report, Report, sets: true
1157
+
1158
+ emits CiFailed
1159
+ end
1160
+
1161
+ command "Supersede" do
1162
+ role "System"
1163
+ goal "Record that a newer commit on main carries a landed one, so its run stops"
1164
+
1165
+ reference_to Integration
1166
+ attribute :landed, Word, sets: true
1167
+ attribute :report, Report, sets: true
1168
+
1169
+ emits IntegrationSuperseded
1170
+ end
1171
+
1172
+ query "Outcome" do
1173
+ description "How one integration step or advance ended: its report, or why it was refused."
1174
+ attribute :run, RunKey
1175
+ where(run: :run)
1176
+ order_by :run
1177
+ end
1178
+ end
1179
+
1180
+ policy "AdvanceWhenAsked" do
1181
+ on "Integration.AdvanceRequested"
1182
+ ask :step, with: { run: :run }
1183
+ end
1184
+
1185
+ policy "RecordTheAdvance" do
1186
+ on "Integration.AdvanceAnswered"
1187
+ trigger Integration::Summarize, with: { report: :report }
1188
+ end
1189
+
1190
+ policy "RecordTheRefusedAdvance" do
1191
+ on "Integration.AdvanceRefused"
1192
+ trigger Integration::Summarize, with: { report: :refusal }
1193
+ end
1194
+
1195
+ policy "VerifyMainWhenRequested" do
1196
+ on "Integration.MainVerificationRequested"
1197
+ ask :check, with: { run: :run, landed: :landed }
1198
+ end
1199
+
1200
+ policy "RecordTheVerification" do
1201
+ on "Integration.VerifyAnswered"
1202
+ where { outcome.value == "verified" }
1203
+ trigger Integration::Pass, with: { landed: :landed, report: :report }
1204
+ end
1205
+
1206
+ policy "RecordTheSupersededVerification" do
1207
+ on "Integration.VerifyAnswered"
1208
+ where { outcome.value == "superseded" }
1209
+ trigger Integration::Supersede, with: { landed: :landed, report: :report }
1210
+ end
1211
+
1212
+ policy "RecordTheFailedVerification" do
1213
+ on "Integration.VerifyRefused"
1214
+ trigger Integration::Fail, with: { landed: :landed, refusal: :refusal }
1215
+ end
1216
+
1217
+ policy "BoardWhenRequested" do
1218
+ on "Integration.MainBoardingRequested"
1219
+ ask :embark, with: { run: :run, landed: :landed }
1220
+ end
1221
+
1222
+ policy "RecordTheBoarding" do
1223
+ on "Integration.BoardAnswered"
1224
+ where { outcome.value == "pushed" }
1225
+ trigger Integration::Send, with: { landed: :landed, pushed: :pushed, report: :report }
1226
+ end
1227
+
1228
+ policy "RecordTheSupersededBoarding" do
1229
+ on "Integration.BoardAnswered"
1230
+ where { outcome.value == "superseded" }
1231
+ trigger Integration::Supersede, with: { landed: :landed, report: :report }
1232
+ end
1233
+
1234
+ policy "RecordTheRefusedBoarding" do
1235
+ on "Integration.BoardRefused"
1236
+ trigger Integration::Reject, with: { landed: :landed, refusal: :refusal }
1237
+ end
1238
+
1239
+ policy "ObserveWhenRequested" do
1240
+ on "Integration.CiObservationRequested"
1241
+ ask :watch, with: { run: :run, landed: :landed }
1242
+ end
1243
+
1244
+ # A CI run still in progress answers `running` and nothing is recorded: the next advance reads
1245
+ # it again.
1246
+ policy "RecordThePassedCi" do
1247
+ on "Integration.ObserveAnswered"
1248
+ where { outcome.value == "passed" }
1249
+ trigger Integration::Green, with: { landed: :landed, report: :report }
1250
+ end
1251
+
1252
+ policy "RecordTheFailedCi" do
1253
+ on "Integration.ObserveAnswered"
1254
+ where { outcome.value == "failed" }
1255
+ trigger Integration::Red, with: { landed: :landed, report: :report }
1256
+ end
1257
+
810
1258
  aggregate "ReviewRequest" do
811
1259
  description "One pull request opened or squash-merged on GitHub, and what GitHub answered."
812
1260
 
@@ -1,8 +1,13 @@
1
1
  # The Memory selection for the Hecks domain: nothing is written to a database. Specs and
2
2
  # pull-request runs use it (`HECKS_ENVIRONMENT=memory`); a real run keeps the PostgresEra
3
3
  # journal named in hecks.world. The overlay's `default_adapter` wins over the base's.
4
+ #
5
+ # The event tap is off as well: the log hecks.world names feeds the owner's pipeline board, and a
6
+ # spec, a gate or a pull-request run must not show up there. A spec that wants the tap builds its
7
+ # own world naming a temporary path.
4
8
  Hecks.world "Hecks" do
5
9
  default_adapter "Memory"
10
+ event_log "None"
6
11
  end
7
12
 
8
13
  Hecks.world "Governance" do
@@ -20,8 +20,16 @@ Hecks.context_map "Hecks" do
20
20
  context "QualityControl"
21
21
  context "Coder"
22
22
  context "Fixer"
23
+ context "PipelineBoard"
24
+ context "Pipeline"
23
25
 
24
26
  # Deploy's `Tenant` is a validated request; Tenancy's `Tenant` is a fact. Tenancy's hecksagon
25
27
  # translates Deploy's `TenantProvisioned` into its own `Register`, so Deploy's model never reaches it.
26
28
  relate "Deploy" => "Tenancy", as: :anticorruption_layer
29
+
30
+ # QualityControl's hecksagon translates the migrate bluebook's `RehearsalAudited` into its own
31
+ # `RecordRehearsalVerdict`, so the audit's model stays out of QualityControl's Maintenance.
32
+ relate "Hecks" => "QualityControl", as: :anticorruption_layer
33
+ # Hecks attaches QualityControl as well, so the pair also shares a kernel, which has no direction.
34
+ relate "QualityControl" => "Hecks", as: :shared_kernel
27
35
  end