hecks 3.10.0 → 3.11.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 (481) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/bluebook/pizzas.bluebook +29 -0
  3. data/examples/pizzas/bluebook/pizzas.hecksagon +7 -0
  4. data/exe/hecks +4 -4
  5. data/lib/hecks/adapters/driven/d1.rb +2 -10
  6. data/lib/hecks/adapters/driven/heki.adapter +1 -1
  7. data/lib/hecks/adapters/driven/heki.rb +2 -12
  8. data/lib/hecks/adapters/driven/lambda.adapter +1 -1
  9. data/lib/hecks/adapters/driven/lambda.rb +3 -18
  10. data/lib/hecks/adapters/driven/postgres.rb +4 -11
  11. data/lib/hecks/adapters/driven/sqlite.adapter +1 -1
  12. data/lib/hecks/adapters/driven/sqlite.rb +2 -10
  13. data/lib/hecks/adapters/driving/admission.rb +46 -0
  14. data/lib/hecks/adapters/driving/cli/nesting.rb +36 -0
  15. data/lib/hecks/adapters/driving/cli/shorthand.rb +88 -0
  16. data/lib/hecks/adapters/driving/cli.rb +127 -0
  17. data/lib/hecks/adapters/driving/cli_runner/answers.rb +160 -0
  18. data/lib/hecks/adapters/driving/cli_runner/resolution.rb +155 -0
  19. data/lib/hecks/adapters/driving/cli_runner/settling.rb +120 -0
  20. data/lib/hecks/adapters/driving/cli_runner/streaming.rb +93 -0
  21. data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +47 -0
  22. data/lib/hecks/adapters/driving/cli_runner.rb +69 -0
  23. data/lib/hecks/adapters/driving/command_request.rb +121 -0
  24. data/lib/hecks/adapters/driving/handle.rb +214 -0
  25. data/lib/hecks/adapters/driving/json.rb +136 -0
  26. data/lib/hecks/adapters/driving/launcher_options.rb +267 -0
  27. data/lib/hecks/adapters/driving/mcp/properties.rb +49 -0
  28. data/lib/hecks/adapters/driving/mcp/tool_calls.rb +116 -0
  29. data/lib/hecks/adapters/driving/mcp/tool_definitions/auditing.rb +53 -0
  30. data/lib/hecks/adapters/driving/mcp/tool_definitions/calling.rb +71 -0
  31. data/lib/hecks/adapters/driving/mcp/tool_definitions/reading.rb +99 -0
  32. data/lib/hecks/adapters/driving/mcp/tool_definitions.rb +18 -0
  33. data/lib/hecks/adapters/driving/mcp.rb +159 -0
  34. data/lib/hecks/adapters/driving/mcp_guide_cache.rb +78 -0
  35. data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +97 -0
  36. data/lib/hecks/adapters/driving/mcp_scope/env_problems.rb +69 -0
  37. data/lib/hecks/adapters/driving/mcp_scope/presenter.rb +83 -0
  38. data/lib/hecks/adapters/driving/mcp_scope.rb +213 -0
  39. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +171 -0
  40. data/lib/hecks/adapters/driving/ruby/chapter.rb +91 -0
  41. data/lib/hecks/adapters/driving/ruby.rb +83 -0
  42. data/lib/hecks/adapters/driving/usage_cache.rb +144 -0
  43. data/lib/hecks/{doors.rb → adapters/driving.rb} +10 -6
  44. data/lib/hecks/behaviors/expectations/boot.rb +1 -1
  45. data/lib/hecks/bench/ruby_runner.rb +1 -1
  46. data/lib/hecks/bluebook/ask_resolution.rb +130 -0
  47. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +8 -2
  48. data/lib/hecks/bluebook/assembly/contracts/rules.rb +4 -2
  49. data/lib/hecks/bluebook/assembly/contracts/structure.rb +3 -1
  50. data/lib/hecks/bluebook/assembly/marks.rb +1 -0
  51. data/lib/hecks/bluebook/attribute.rb +1 -1
  52. data/lib/hecks/bluebook/behaviour/command.rb +13 -8
  53. data/lib/hecks/bluebook/behaviour/policy.rb +30 -0
  54. data/lib/hecks/bluebook/capabilities/attribute_values.rb +72 -0
  55. data/lib/hecks/bluebook/capabilities.rb +91 -9
  56. data/lib/hecks/bluebook/domain_port.rb +16 -4
  57. data/lib/hecks/bluebook/dsl/adapter_builder.rb +18 -6
  58. data/lib/hecks/bluebook/dsl/binding_proxy.rb +13 -0
  59. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/computed_sources.rb +98 -0
  60. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/fan_out_rows.rb +42 -0
  61. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +14 -2
  62. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +69 -3
  63. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +17 -10
  64. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +5 -0
  65. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
  66. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +8 -1
  67. data/lib/hecks/bluebook/dsl/command_builder/operands.rb +121 -0
  68. data/lib/hecks/bluebook/dsl/command_builder.rb +2 -0
  69. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +10 -1
  70. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +45 -2
  71. data/lib/hecks/bluebook/dsl/policy_builder.rb +47 -10
  72. data/lib/hecks/bluebook/dsl/rule_reference.rb +7 -4
  73. data/lib/hecks/bluebook/dsl/world_builder.rb +1 -1
  74. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +6 -0
  75. data/lib/hecks/bluebook/expression/ast_json.rb +9 -6
  76. data/lib/hecks/bluebook/expression/ast_reader.rb +14 -9
  77. data/lib/hecks/bluebook/expression/projection.json +36 -0
  78. data/lib/hecks/bluebook/expression/resolver/operations.rb +31 -0
  79. data/lib/hecks/bluebook/expression/resolver/parsing.rb +38 -5
  80. data/lib/hecks/bluebook/expression/resolver/scanning.rb +22 -5
  81. data/lib/hecks/bluebook/expression/resolver/values.rb +10 -0
  82. data/lib/hecks/bluebook/expression/resolver.rb +20 -1
  83. data/lib/hecks/bluebook/hecksagon.rb +23 -3
  84. data/lib/hecks/bluebook/lifecycle.rb +22 -3
  85. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +13 -1
  86. data/lib/hecks/bluebook/meta_validator/modes.rb +4 -1
  87. data/lib/hecks/bluebook/meta_validator/readings.rb +18 -1
  88. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +2 -1
  89. data/lib/hecks/bluebook/meta_validator/shapes.rb +5 -0
  90. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +1 -1
  91. data/lib/hecks/bluebook/meta_validator.rb +12 -12
  92. data/lib/hecks/bluebook/model_check/ask_checks.rb +71 -0
  93. data/lib/hecks/bluebook/model_check/policy_checks.rb +2 -1
  94. data/lib/hecks/bluebook/model_check/reference_checks.rb +70 -0
  95. data/lib/hecks/bluebook/model_check.rb +8 -2
  96. data/lib/hecks/bluebook/policy.rb +4 -2
  97. data/lib/hecks/bluebook/smoke_test.rb +1 -1
  98. data/lib/hecks/bluebook/synthesizer.rb +2 -0
  99. data/lib/hecks/bluebook.rb +1 -0
  100. data/lib/hecks/cli/command_table.rb +1 -1
  101. data/lib/hecks/cli/console.rb +2 -1
  102. data/lib/hecks/cli/document.rb +1 -1
  103. data/lib/hecks/cli/launcher_words.rb +4 -4
  104. data/lib/hecks/cli/mcp.rb +4 -4
  105. data/lib/hecks/cli/project_cli/launcher_source.rb +2 -2
  106. data/lib/hecks/cli/project_cli/templates.rb +5 -5
  107. data/lib/hecks/cli/project_cli.rb +9 -6
  108. data/lib/hecks/cli/run.rb +2 -2
  109. data/lib/hecks/cli/smoke_http/checks.rb +4 -1
  110. data/lib/hecks/cli/smoke_http/transport.rb +3 -3
  111. data/lib/hecks/cli/smoke_http.rb +3 -0
  112. data/lib/hecks/codemod.rb +5 -2
  113. data/lib/hecks/corpus/routes.rb +7 -0
  114. data/lib/hecks/corpus/rust.rb +3 -2
  115. data/lib/hecks/deploy/bluebook/deploy.bluebook +18 -2
  116. data/lib/hecks/doc/reference/rendering.rb +6 -3
  117. data/lib/hecks/forms/app/commands.rb +8 -7
  118. data/lib/hecks/forms/app/queries.rb +2 -1
  119. data/lib/hecks/forms/app.rb +1 -1
  120. data/lib/hecks/forms/record_renderer.rb +1 -1
  121. data/lib/hecks/framework/bluebook/privacy.bluebook +11 -0
  122. data/lib/hecks/fuzzing/concurrent_dispatch.rb +4 -1
  123. data/lib/hecks/fuzzing/failure_triage.rb +2 -1
  124. data/lib/hecks/fuzzing/mutation/run.rb +11 -4
  125. data/lib/hecks/fuzzing/properties/catalog.rb +6 -4
  126. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +18 -11
  127. data/lib/hecks/fuzzing/properties/guards.rb +1 -1
  128. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +1 -1
  129. data/lib/hecks/fuzzing/self_consistency.rb +6 -2
  130. data/lib/hecks/fuzzing/shrinker.rb +3 -1
  131. data/lib/hecks/fuzzing/value_generator.rb +19 -5
  132. data/lib/hecks/gate/stages.yml +4 -10
  133. data/lib/hecks/grammar/evolve.rb +1 -1
  134. data/lib/hecks/grammar/expression_operators.json +372 -0
  135. data/lib/hecks/grammar/operators.rb +3 -1
  136. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +10 -10
  137. data/lib/hecks/hecks/adapters/codebase/inspection/rubycritic.rb +35 -0
  138. data/lib/hecks/hecks/adapters/codebase/inspection.rb +104 -0
  139. data/lib/hecks/hecks/adapters/codebase/publishing.rb +2 -1
  140. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +12 -2
  141. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +2 -1
  142. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +1 -1
  143. data/lib/hecks/hecks/adapters/cost_explorer.rb +8 -5
  144. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +2 -1
  145. data/lib/hecks/hecks/adapters/finding_github.rb +13 -6
  146. data/lib/hecks/hecks/adapters/first_admin.rb +2 -2
  147. data/lib/hecks/hecks/adapters/github_rulesets.rb +6 -3
  148. data/lib/hecks/hecks/adapters/in_process_boot.rb +1 -1
  149. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +1 -1
  150. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +10 -20
  151. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +28 -5
  152. data/lib/hecks/hecks/adapters/local_files.rb +2 -2
  153. data/lib/hecks/hecks/adapters/rehearsal/audit_report.rb +107 -0
  154. data/lib/hecks/hecks/adapters/rehearsal/census.rb +71 -0
  155. data/lib/hecks/hecks/adapters/rehearsal/declaration.rb +133 -0
  156. data/lib/hecks/hecks/adapters/rehearsal/environment.rb +83 -0
  157. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +142 -0
  158. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +96 -0
  159. data/lib/hecks/hecks/adapters/rehearsal/postgres_census.rb +100 -0
  160. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +69 -0
  161. data/lib/hecks/hecks/adapters/rehearsal/postgres_store.rb +129 -0
  162. data/lib/hecks/hecks/adapters/rehearsal/rows.rb +41 -0
  163. data/lib/hecks/hecks/adapters/rehearsal/rust_audit.rb +83 -0
  164. data/lib/hecks/hecks/adapters/rehearsal/subject.rb +104 -0
  165. data/lib/hecks/hecks/adapters/rehearsal.rb +54 -0
  166. data/lib/hecks/hecks/adapters/rehearsal_store.adapter +7 -0
  167. data/lib/hecks/hecks/adapters/rehearsal_store.rb +81 -0
  168. data/lib/hecks/hecks/adapters/terminal.rb +13 -11
  169. data/lib/hecks/hecks/codebase.behaviors +13 -1
  170. data/lib/hecks/hecks/codebase.bluebook +239 -5
  171. data/lib/hecks/hecks/custodian.behaviors +24 -6
  172. data/lib/hecks/hecks/custodian.bluebook +6 -1227
  173. data/lib/hecks/hecks/deploy.behaviors +1 -1
  174. data/lib/hecks/hecks/deploy.world +1 -3
  175. data/lib/hecks/hecks/hecks.behaviors +1 -1
  176. data/lib/hecks/hecks/hecks.hecksagon +53 -18
  177. data/lib/hecks/hecks/hecks.world +10 -10
  178. data/lib/hecks/hecks/rehearsal.bluebook +477 -0
  179. data/lib/hecks/hecks/site.behaviors +1 -1
  180. data/lib/hecks/hecks/site.world +0 -1
  181. data/lib/hecks/hecks/tooling.bluebook +1238 -0
  182. data/lib/hecks/indifferent_key.rb +20 -0
  183. data/lib/hecks/language/adapter.bluebook +13 -3
  184. data/lib/hecks/language/bluebook/aggregate.bluebook +23 -0
  185. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -0
  186. data/lib/hecks/language/bluebook/entity.bluebook +18 -0
  187. data/lib/hecks/language/bluebook/policy.bluebook +9 -1
  188. data/lib/hecks/language/bluebook/query.bluebook +1 -1
  189. data/lib/hecks/language/bluebook/vocabulary.bluebook +11 -4
  190. data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -1
  191. data/lib/hecks/language/hecksagon/hecksagon.bluebook +22 -0
  192. data/lib/hecks/language/oidc.json +10 -0
  193. data/lib/hecks/language/port.bluebook +4 -4
  194. data/lib/hecks/literal.rb +12 -3
  195. data/lib/hecks/ports/key_vault.rb +7 -2
  196. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +21 -10
  197. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +4 -2
  198. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +2 -1
  199. data/lib/hecks/ports/persistence/repository_factory.rb +6 -3
  200. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +29 -0
  201. data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +1 -1
  202. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  203. data/lib/hecks/projections/deploy/shared.rb +5 -2
  204. data/lib/hecks/projections/model/deviations.rb +2 -2
  205. data/lib/hecks/projections/model.rb +2 -2
  206. data/lib/hecks/projections/oidc.rb +13 -1
  207. data/lib/hecks/projections/shape.rb +5 -2
  208. data/lib/hecks/projections/site/cms_editor/attributes.rb +26 -6
  209. data/lib/hecks/projections/site/cms_editor/blocks.rb +157 -0
  210. data/lib/hecks/projections/site/cms_editor/checks.rb +14 -1
  211. data/lib/hecks/projections/site/cms_editor/clearing.rb +70 -0
  212. data/lib/hecks/projections/site/cms_editor/color.rb +124 -0
  213. data/lib/hecks/projections/site/cms_editor/composition.rb +42 -0
  214. data/lib/hecks/projections/site/cms_editor/destructive.rb +61 -0
  215. data/lib/hecks/projections/site/cms_editor/drafts.rb +102 -0
  216. data/lib/hecks/projections/site/cms_editor/hints.rb +74 -0
  217. data/lib/hecks/projections/site/cms_editor/icons.rb +86 -0
  218. data/lib/hecks/projections/site/cms_editor/key_kinds.rb +31 -0
  219. data/lib/hecks/projections/site/cms_editor/limits.rb +72 -0
  220. data/lib/hecks/projections/site/cms_editor/media.rb +1 -1
  221. data/lib/hecks/projections/site/cms_editor/moment.rb +34 -0
  222. data/lib/hecks/projections/site/cms_editor/palette.rb +115 -0
  223. data/lib/hecks/projections/site/cms_editor/pickers.rb +85 -0
  224. data/lib/hecks/projections/site/cms_editor/preview.rb +91 -0
  225. data/lib/hecks/projections/site/cms_editor/relations.rb +92 -0
  226. data/lib/hecks/projections/site/cms_editor/scale_checks.rb +66 -0
  227. data/lib/hecks/projections/site/cms_editor/scheduling.rb +150 -0
  228. data/lib/hecks/projections/site/cms_editor/schema.rb +96 -19
  229. data/lib/hecks/projections/site/cms_editor/setting.rb +52 -9
  230. data/lib/hecks/projections/site/cms_editor/targets.rb +86 -0
  231. data/lib/hecks/projections/site/cms_editor/templates/package.json.tmpl +18 -1
  232. data/lib/hecks/projections/site/cms_editor/templates/src/app.ts.tmpl +251 -57
  233. data/lib/hecks/projections/site/cms_editor/templates/src/assets.ts.tmpl +98 -0
  234. data/lib/hecks/projections/site/cms_editor/templates/src/auth/membership.ts.tmpl +32 -24
  235. data/lib/hecks/projections/site/cms_editor/templates/src/browser/app.css.tmpl +412 -0
  236. data/lib/hecks/projections/site/cms_editor/templates/src/browser/autosave.js.tmpl +144 -0
  237. data/lib/hecks/projections/site/cms_editor/templates/src/browser/blocks.js.tmpl +500 -0
  238. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_doc.js.tmpl +175 -0
  239. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_editor.js.tmpl +418 -0
  240. data/lib/hecks/projections/site/cms_editor/templates/src/browser/epoch.js.tmpl +61 -0
  241. data/lib/hecks/projections/site/cms_editor/templates/src/browser/forms.js.tmpl +210 -0
  242. data/lib/hecks/projections/site/cms_editor/templates/src/browser/lists.js.tmpl +40 -0
  243. data/lib/hecks/projections/site/cms_editor/templates/src/browser/main.js.tmpl +26 -0
  244. data/lib/hecks/projections/site/cms_editor/templates/src/browser/media_picker.js.tmpl +232 -0
  245. data/lib/hecks/projections/site/cms_editor/templates/src/browser/moments.js.tmpl +73 -0
  246. data/lib/hecks/projections/site/cms_editor/templates/src/browser/pickers.js.tmpl +152 -0
  247. data/lib/hecks/projections/site/cms_editor/templates/src/browser/preview.js.tmpl +98 -0
  248. data/lib/hecks/projections/site/cms_editor/templates/src/browser/shell.js.tmpl +140 -0
  249. data/lib/hecks/projections/site/cms_editor/templates/src/browser/toast.js.tmpl +66 -0
  250. data/lib/hecks/projections/site/cms_editor/templates/src/choices.ts.tmpl +99 -0
  251. data/lib/hecks/projections/site/cms_editor/templates/src/commands.ts.tmpl +78 -24
  252. data/lib/hecks/projections/site/cms_editor/templates/src/config.ts.tmpl +6 -0
  253. data/lib/hecks/projections/site/cms_editor/templates/src/flash.ts.tmpl +52 -0
  254. data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +19 -2
  255. data/lib/hecks/projections/site/cms_editor/templates/src/media/handler.ts.tmpl +31 -8
  256. data/lib/hecks/projections/site/cms_editor/templates/src/names.ts.tmpl +36 -0
  257. data/lib/hecks/projections/site/cms_editor/templates/src/schema.ts.tmpl +131 -2
  258. data/lib/hecks/projections/site/cms_editor/templates/src/ui/availability.ts.tmpl +15 -0
  259. data/lib/hecks/projections/site/cms_editor/templates/src/ui/block_list.js.tmpl +213 -0
  260. data/lib/hecks/projections/site/cms_editor/templates/src/ui/blocks.ts.tmpl +275 -0
  261. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_model.js.tmpl +8 -5
  262. data/lib/hecks/projections/site/cms_editor/templates/src/ui/detail.ts.tmpl +88 -0
  263. data/lib/hecks/projections/site/cms_editor/templates/src/ui/dialogs.ts.tmpl +43 -0
  264. data/lib/hecks/projections/site/cms_editor/templates/src/ui/fields.ts.tmpl +229 -34
  265. data/lib/hecks/projections/site/cms_editor/templates/src/ui/html.ts.tmpl +40 -81
  266. data/lib/hecks/projections/site/cms_editor/templates/src/ui/icons.ts.tmpl +15 -0
  267. data/lib/hecks/projections/site/cms_editor/templates/src/ui/input.ts.tmpl +29 -12
  268. data/lib/hecks/projections/site/cms_editor/templates/src/ui/links.ts.tmpl +100 -0
  269. data/lib/hecks/projections/site/cms_editor/templates/src/ui/moments.ts.tmpl +44 -0
  270. data/lib/hecks/projections/site/cms_editor/templates/src/ui/outline.ts.tmpl +53 -17
  271. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pages.ts.tmpl +178 -88
  272. data/lib/hecks/projections/site/cms_editor/templates/src/ui/paging.ts.tmpl +82 -0
  273. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pickers.ts.tmpl +110 -0
  274. data/lib/hecks/projections/site/cms_editor/templates/src/ui/preview.ts.tmpl +87 -0
  275. data/lib/hecks/projections/site/cms_editor/templates/src/ui/related.ts.tmpl +97 -0
  276. data/lib/hecks/projections/site/cms_editor/templates/src/ui/schedule.ts.tmpl +160 -0
  277. data/lib/hecks/projections/site/cms_editor/templates/src/ui/shell.ts.tmpl +211 -0
  278. data/lib/hecks/projections/site/cms_editor/templates/src/ui/table.ts.tmpl +151 -0
  279. data/lib/hecks/projections/site/cms_editor/templates/src/ui/theme.js.tmpl +16 -0
  280. data/lib/hecks/projections/site/cms_editor/templates/src/ui/values.ts.tmpl +69 -0
  281. data/lib/hecks/projections/site/cms_editor/templates/src/ui/words.ts.tmpl +97 -0
  282. data/lib/hecks/projections/site/cms_editor/templates/src/ui/world.ts.tmpl +35 -0
  283. data/lib/hecks/projections/site/cms_editor/templates/tsconfig.json.tmpl +2 -1
  284. data/lib/hecks/projections/site/cms_editor/theme.rb +29 -0
  285. data/lib/hecks/projections/site/cms_editor/theme_checks.rb +57 -0
  286. data/lib/hecks/projections/site/cms_editor.rb +49 -23
  287. data/lib/hecks/projections/site/role_probe.rb +2 -0
  288. data/lib/hecks/projector/cli_audience.rb +2 -1
  289. data/lib/hecks/projector/cli_projector/listing.rb +1 -1
  290. data/lib/hecks/projector/cli_projector/option_specs.rb +1 -1
  291. data/lib/hecks/projector/docs_projector/closing.rb +1 -1
  292. data/lib/hecks/projector/docs_projector.rb +1 -1
  293. data/lib/hecks/projector/exporter/bindings.rb +40 -10
  294. data/lib/hecks/projector/exporter/capability_values.rb +55 -0
  295. data/lib/hecks/projector/narrate_projector/reactions.rb +1 -1
  296. data/lib/hecks/projector/target.rb +11 -0
  297. data/lib/hecks/projector.rb +32 -5
  298. data/lib/hecks/quality_control/adapters/github_checks.rb +12 -8
  299. data/lib/hecks/quality_control/adapters/github_issues.rb +8 -4
  300. data/lib/hecks/quality_control/cli/qa_open_pr.rb +2 -2
  301. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +1 -1
  302. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +1 -1
  303. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  304. data/lib/hecks/quality_control/quality_control.bluebook +6 -2
  305. data/lib/hecks/release/approval.rb +64 -0
  306. data/lib/hecks/router/{door.rb → aggregate_reader.rb} +5 -4
  307. data/lib/hecks/router/namespace_installer.rb +16 -16
  308. data/lib/hecks/router.rb +1 -1
  309. data/lib/hecks/runtime/best_effort.rb +22 -0
  310. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -2
  311. data/lib/hecks/runtime/command_interpreter.rb +3 -2
  312. data/lib/hecks/runtime/command_rules/emission.rb +1 -1
  313. data/lib/hecks/runtime/dispatcher.rb +4 -4
  314. data/lib/hecks/runtime/entity_element/location.rb +1 -1
  315. data/lib/hecks/runtime/event.rb +5 -0
  316. data/lib/hecks/runtime/identity.rb +7 -6
  317. data/lib/hecks/runtime/interpreting.rb +2 -1
  318. data/lib/hecks/runtime/invocation_builder.rb +1 -1
  319. data/lib/hecks/runtime/loader/boot_steps.rb +8 -5
  320. data/lib/hecks/runtime/loader.rb +10 -10
  321. data/lib/hecks/runtime/policy_interpreter/arguments.rb +7 -4
  322. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +3 -3
  323. data/lib/hecks/runtime/policy_interpreter.rb +6 -6
  324. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -1
  325. data/lib/hecks/runtime/reaction_invocation.rb +1 -1
  326. data/lib/hecks/runtime/rebuild_sweep.rb +11 -1
  327. data/lib/hecks/runtime/registry/ask_verification.rb +35 -0
  328. data/lib/hecks/runtime/registry/hecksagon_rules.rb +10 -0
  329. data/lib/hecks/runtime/registry/merging.rb +1 -1
  330. data/lib/hecks/runtime/registry/providers.rb +16 -0
  331. data/lib/hecks/runtime/registry/read_repository.rb +6 -4
  332. data/lib/hecks/runtime/registry/verification.rb +4 -1
  333. data/lib/hecks/runtime/registry/world_defaults.rb +29 -0
  334. data/lib/hecks/runtime/registry.rb +1 -1
  335. data/lib/hecks/runtime/saga_interpreter/compensation.rb +1 -1
  336. data/lib/hecks/runtime/saga_interpreter/delivery.rb +4 -4
  337. data/lib/hecks/runtime/saga_interpreter/transitions.rb +1 -1
  338. data/lib/hecks/runtime/saga_interpreter.rb +3 -3
  339. data/lib/hecks/runtime/tenant_check.rb +5 -4
  340. data/lib/hecks/runtime/value/coercion.rb +2 -2
  341. data/lib/hecks/runtime/value/validation.rb +16 -4
  342. data/lib/hecks/runtime.rb +9 -9
  343. data/lib/hecks/rust_build/project_rust/target_ir.rb +1 -1
  344. data/lib/hecks/rust_build/wasm.rb +1 -1
  345. data/lib/hecks/rust_build/wasm_browser.rb +1 -1
  346. data/lib/hecks/rust_build.rb +11 -0
  347. data/lib/hecks/served_options.rb +53 -0
  348. data/lib/hecks/site/bluebook/site.bluebook +1 -0
  349. data/lib/hecks/storehouse/audit.rb +1 -1
  350. data/lib/hecks/storehouse/dispatching.rb +8 -6
  351. data/lib/hecks/storehouse/introspection.rb +2 -2
  352. data/lib/hecks/storehouse/querying.rb +6 -4
  353. data/lib/hecks/storehouse.rb +4 -4
  354. data/lib/hecks/tools/comment_style/source_file.rb +4 -1
  355. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +4 -1
  356. data/lib/hecks/tools/lanes/rows.rb +6 -0
  357. data/lib/hecks/tools/oidc_manifests.rb +4 -5
  358. data/lib/hecks/tools/regeneration_run.rb +11 -4
  359. data/lib/hecks/tools/site_routes/editor_files.rb +12 -5
  360. data/lib/hecks/tools/tenant_provisioning.rb +2 -2
  361. data/lib/hecks/tools/tools_doc.rb +4 -4
  362. data/lib/hecks/version.rb +1 -1
  363. data/lib/hecks/vocabulary.rb +4 -4
  364. data/lib/hecks.rb +15 -15
  365. data/lib/rubocop/cop/hecks/env_dump.rb +69 -0
  366. data/lib/rubocop/cop/hecks/monotonic_duration.rb +53 -0
  367. data/lib/rubocop/cop/hecks/no_wall_clock_in_runtime.rb +34 -0
  368. data/lib/rubocop/cop/hecks/raw_shell_interpolation.rb +79 -0
  369. data/lib/rubocop/cop/hecks/sleep_in_spec.rb +34 -0
  370. data/lib/rubocop/cop/hecks/swallowed_rescue.rb +37 -0
  371. data/lib/rubocop/cop/hecks/symbol_string_key_mix.rb +50 -0
  372. data/lib/rubocop/cop/hecks/untyped_raise.rb +37 -0
  373. data/prebuilt/05c358d38d661a3774f813d49c66f5b68939af94432d66257a56f49ee2598994.marshal +0 -0
  374. data/prebuilt/26c40c61f09b09b11651c64668eda3ceb180f83cf2a3802d3033d2fd99ac841b.marshal +0 -0
  375. data/prebuilt/verdicts-230ac18c25abfd3d92ede032bee2661a4c2cd2773ab0cf0e2ae52546ba2f7af9.json +1 -0
  376. data/rust/.gitignore +6 -0
  377. data/rust/Cargo.toml +6 -0
  378. data/rust/build/src/binding_pass.rs +103 -0
  379. data/rust/build/src/cargo_sync.rs +6 -0
  380. data/rust/build/src/lineage_pass.rs +3 -3
  381. data/rust/build/src/main.rs +17 -5
  382. data/rust/build/src/pipeline.rs +48 -5
  383. data/rust/build/src/seams_pass.rs +123 -0
  384. data/rust/build/src/translation_pass.rs +167 -0
  385. data/rust/codegen/src/asks.rs +103 -0
  386. data/rust/codegen/src/commands.rs +13 -8
  387. data/rust/codegen/src/constraints.rs +25 -0
  388. data/rust/codegen/src/domain_generator.rs +2 -0
  389. data/rust/codegen/src/expr_emitter.rs +13 -0
  390. data/rust/codegen/src/json_codec.rs +54 -15
  391. data/rust/codegen/src/main.rs +1 -0
  392. data/rust/codegen/src/mutations.rs +128 -3
  393. data/rust/codegen/src/queries.rs +11 -2
  394. data/rust/codegen/src/reactions.rs +1 -1
  395. data/rust/codegen/src/types.rs +166 -8
  396. data/rust/host/HECKS_RELEASE +1 -1
  397. data/rust/host/src/api.rs +4 -4
  398. data/rust/host/src/bin/validate_harness.rs +43 -0
  399. data/rust/host/src/boundary_fuzz/expr_json.rs +2 -2
  400. data/rust/host/src/boundary_fuzz/ir.rs +1 -0
  401. data/rust/host/src/boundary_fuzz/server.rs +1 -1
  402. data/rust/host/src/checkout.rs +35 -19
  403. data/rust/host/src/commerce_ir.rs +408 -2
  404. data/rust/host/src/expr_json.rs +118 -0
  405. data/rust/host/src/mint.rs +1 -1
  406. data/rust/host/src/payments/tests.rs +27 -1
  407. data/rust/host/src/payments.rs +12 -4
  408. data/rust/host/src/query_step.rs +22 -4
  409. data/rust/host/src/reference_validate.rs +653 -108
  410. data/rust/host/src/resend.rs +2 -0
  411. data/rust/host/src/server.rs +19 -6
  412. data/rust/host/src/ui_schema.rs +132 -5
  413. data/rust/host/src/web/newsletter.rs +7 -8
  414. data/rust/host/src/web/newsletter_send.rs +38 -13
  415. data/rust/host/src/web/registrations.rs +229 -26
  416. data/rust/host/src/web.rs +3 -3
  417. data/rust/parser/src/emit.rs +38 -6
  418. data/rust/parser/src/expr/ast_json.rs +7 -1
  419. data/rust/parser/src/expr/resolver.rs +171 -6
  420. data/rust/parser/src/ir.rs +7 -0
  421. data/rust/parser/src/keywords.rs +24 -0
  422. data/rust/parser/src/main.rs +3 -0
  423. data/rust/parser/src/parse/aggregate.rs +2 -1
  424. data/rust/parser/src/parse/chapter.rs +2 -2
  425. data/rust/parser/src/parse/command.rs +2 -0
  426. data/rust/parser/src/parse/hecksagon.rs +5 -2
  427. data/rust/parser/src/parse/lifecycle.rs +81 -0
  428. data/rust/parser/src/parse/mod.rs +15 -1
  429. data/rust/parser/src/parse/policy.rs +13 -2
  430. data/rust/parser/src/parse/value_object.rs +13 -8
  431. data/rust/parser/src/ruby_value.rs +1 -1
  432. data/rust/src/exemplar/commands.rs +4 -4
  433. data/rust/src/exemplar/constraints.rs +1 -1
  434. data/rust/src/exemplar/json.rs +43 -1
  435. data/rust/src/kernel/cli.rs +7 -5
  436. data/rust/src/kernel/dispatch.rs +2 -2
  437. data/rust/src/kernel/dispatch_guard_tests.rs +1 -1
  438. data/rust/src/kernel/expr.rs +66 -3
  439. data/rust/src/kernel/expression_operators/arithmetic.rs +130 -5
  440. data/rust/src/kernel/expression_operators/text.rs +26 -2
  441. data/rust/src/kernel/json.rs +15 -0
  442. data/rust/src/kernel/mod.rs +1 -1
  443. data/rust/src/kernel/orchestrate.rs +54 -5
  444. data/rust/src/kernel/orchestrate_guard_tests.rs +67 -0
  445. data/rust/src/kernel/pattern.rs +60 -0
  446. data/rust/src/kernel/reference_lookup.rs +90 -7
  447. metadata +140 -38
  448. data/lib/hecks/doors/cli_door/nesting.rb +0 -34
  449. data/lib/hecks/doors/cli_door/shorthand.rb +0 -85
  450. data/lib/hecks/doors/cli_door.rb +0 -124
  451. data/lib/hecks/doors/cli_runner/answers.rb +0 -138
  452. data/lib/hecks/doors/cli_runner/resolution.rb +0 -146
  453. data/lib/hecks/doors/cli_runner/settling.rb +0 -115
  454. data/lib/hecks/doors/cli_runner/streaming.rb +0 -90
  455. data/lib/hecks/doors/cli_runner/suggestions.rb +0 -43
  456. data/lib/hecks/doors/cli_runner.rb +0 -66
  457. data/lib/hecks/doors/command_request.rb +0 -119
  458. data/lib/hecks/doors/handle.rb +0 -208
  459. data/lib/hecks/doors/json_door.rb +0 -132
  460. data/lib/hecks/doors/launcher_options.rb +0 -247
  461. data/lib/hecks/doors/mcp_door/properties.rb +0 -47
  462. data/lib/hecks/doors/mcp_door/tool_calls.rb +0 -113
  463. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +0 -51
  464. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +0 -69
  465. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +0 -97
  466. data/lib/hecks/doors/mcp_door/tool_definitions.rb +0 -15
  467. data/lib/hecks/doors/mcp_door.rb +0 -156
  468. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +0 -92
  469. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +0 -55
  470. data/lib/hecks/doors/mcp_door_scope/presenter.rb +0 -78
  471. data/lib/hecks/doors/mcp_door_scope.rb +0 -201
  472. data/lib/hecks/doors/mcp_guide_cache.rb +0 -75
  473. data/lib/hecks/doors/ruby_door/aggregate_door.rb +0 -162
  474. data/lib/hecks/doors/ruby_door/chapter.rb +0 -89
  475. data/lib/hecks/doors/ruby_door.rb +0 -80
  476. data/lib/hecks/doors/usage_cache.rb +0 -139
  477. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_widget.js.tmpl +0 -282
  478. data/lib/hecks/projections/site/cms_editor/templates/src/ui/media_picker.js.tmpl +0 -109
  479. data/prebuilt/c28d6d9db14eea3e17161e9d9c262efee30b256cf97693a7cfd552bce24b2f7f.marshal +0 -0
  480. data/prebuilt/cb375cba61ca0dbe8ddb9739c306510fe05e5f4b7a9b6955caff8224c63ea0e0.marshal +0 -0
  481. data/prebuilt/verdicts-d6d584ad43b5f3cebf88aafbbdbf024c38574acf18e06adffbc555f7786b1c2f.json +0 -1
@@ -1,236 +1,7 @@
1
1
  Hecks.bluebook "Hecks" do
2
- # Custodian: operating any domain. Each aggregate here is a concern a client runs against
3
- # their own domain (ADR 0080, section 2).
4
-
5
- aggregate "Introspection" do
6
- description "A look at a booted domain, answered by the runtime without changing anything."
7
-
8
- attribute :domain, DomainPath
9
- identified_by :domain
10
-
11
- value_object "DomainPath" do
12
- attribute :value, String, pattern: '[^\t\n\r]'
13
-
14
- invariant("a domain is named by its path") { !value.to_s.empty? }
15
- end
16
-
17
- value_object "ChapterName" do
18
- attribute :value, String, pattern: '[^ \t\n\r]'
19
-
20
- invariant("a chapter is named") { !value.to_s.empty? }
21
- end
22
-
23
- value_object "AggregateName" do
24
- attribute :value, String, pattern: '[^ \t\n\r]'
25
-
26
- invariant("an aggregate is named") { !value.to_s.empty? }
27
- end
28
-
29
- # Each query below is answered by the DomainRuntime port's adapter: the domain is booted
30
- # in-process and the answer is the exact text the matching bin script printed.
31
-
32
- # An answer that is one document of text, exactly as the tool that produced it wrote it.
33
- value_object "Document" do
34
- attribute :text, String
35
- end
36
-
37
- query "Ir" do
38
- description "The IR a domain's boot produces, as JSON: what golden specs pin and an era hashes."
39
- attribute :domain, DomainPath, optional: true
40
- attribute :translations, Boolean, optional: true
41
- attribute :meta, Boolean, optional: true
42
- returns Document
43
- end
44
-
45
- query "Shape" do
46
- description "The storage shape an era's label is minted from: a bluebook file or a directory of them."
47
- attribute :domain, DomainPath
48
- returns Document
49
- end
50
-
51
- query "Stores" do
52
- description "Every aggregate's current records: the head, not the journal."
53
- attribute :domain, DomainPath
54
- returns Document
55
- end
56
-
57
- query "History" do
58
- description "Every journal entry a domain's append-only adapters hold: the whole write history."
59
- attribute :domain, DomainPath
60
- returns Document
61
- end
62
-
63
- query "Statements" do
64
- description "A chapter's declared facts, as plain English sentences."
65
- attribute :domain, DomainPath
66
- attribute :chapter, ChapterName
67
- returns Document
68
- end
69
-
70
- query "Narrate" do
71
- description "A domain read back in English, whole or for one aggregate."
72
- attribute :domain, DomainPath, optional: true
73
- attribute :aggregate, AggregateName, optional: true
74
- returns Document
75
- end
76
-
77
- query "Docs" do
78
- description "A domain's usage document, whole or for one aggregate."
79
- attribute :domain, DomainPath, optional: true
80
- attribute :aggregate, AggregateName, optional: true
81
- returns Document
82
- end
83
-
84
- # One file a projection would have written, held as its name and its text.
85
- value_object "ProjectedFile" do
86
- attribute :name, String
87
- attribute :text, String
88
- end
89
-
90
- query "ProjectDiagrams" do
91
- description "A chapter's Mermaid diagrams, as file names mapped to their text; nothing is written."
92
- attribute :domain, DomainPath
93
- attribute :chapter, ChapterName
94
- returns list_of(ProjectedFile)
95
- end
96
-
97
- query "Glossary" do
98
- description "A chapter's Ubiquitous Language glossary, as file names mapped to their text; nothing is written."
99
- attribute :domain, DomainPath
100
- attribute :chapter, ChapterName
101
- returns list_of(ProjectedFile)
102
- end
103
- end
104
-
105
- # A journaled command whose work happens outside the runtime (ADR 0080, section 11). Every
106
- # command below that runs something follows this one shape, so later aggregates copy it:
107
- #
108
- # 1. A creating command records the request as a record in state "requested" and emits.
109
- # 2. A policy on that event triggers an ask on one of the record's ports. The runtime hands
110
- # the port's adapter the whole record, so the adapter does all the IO, and only there.
111
- # 3. The adapter answers (a hash named like a command's arguments) or raises (its message
112
- # is the refusal). One policy per outcome re-enters the record with a command that stores it.
113
- #
114
- # The ports are declared in hecks.hecksagon; each adapter is in adapters/.
115
-
116
- aggregate "ModelCheckRun" do
117
- description "One static analysis over domains' models, and what it found: a check's history."
118
-
119
- attribute :run, RunKey
120
- attribute :domains, DomainList, optional: true
121
- attribute :profile, ProfileName, optional: true
122
- attribute :strict, Switch, optional: true
123
- attribute :report, Report, optional: true
124
- attribute :checked, Checked, optional: true
125
- attribute :refusal, Report, optional: true
126
- identified_by :run
127
-
128
- value_object "RunKey" do
129
- attribute :value, String, pattern: '[^ \t\n\r]'
130
-
131
- invariant("a run is named") { !value.to_s.empty? }
132
- end
133
-
134
- value_object "DomainList" do
135
- attribute :value, String, pattern: '[^\t\n\r]'
136
- end
137
-
138
- value_object "ProfileName" do
139
- attribute :value, String, pattern: '^client$'
140
- end
141
-
142
- value_object "Switch" do
143
- attribute :value, Boolean
144
- end
145
-
146
- value_object "Report" do
147
- attribute :value, String
148
- end
149
-
150
- # How many domains the report examined, counted from its headers so a reader need not.
151
- value_object "Checked" do
152
- attribute :value, Integer
153
-
154
- invariant("a count is not negative") { value >= 0 }
155
- end
156
-
157
- lifecycle :status, default: "requested" do
158
- transition "Pass" => "clean", from: "requested"
159
- transition "Flag" => "flagged", from: "requested"
160
- end
161
-
162
- command "ModelCheck" do
163
- role "Operator"
164
- goal "Check domains for dead states and unreachable steps, and keep the verdict"
165
-
166
- attribute :run, RunKey
167
- attribute :domains, DomainList, optional: true
168
- attribute :profile, ProfileName, optional: true
169
- attribute :strict, Switch, optional: true
170
-
171
- sets :run
172
- sets :domains
173
- sets :profile
174
- sets :strict
175
-
176
- emits ModelCheckRequested
177
- end
178
-
179
- command "Pass" do
180
- role "System"
181
- goal "Record that the analysis left no error"
182
-
183
- reference_to ModelCheckRun
184
- attribute :report, Report
185
- attribute :checked, Checked
186
-
187
- sets :report
188
- sets :checked
189
-
190
- emits ModelCheckPassed
191
- end
192
-
193
- command "Flag" do
194
- role "System"
195
- goal "Record that the analysis found something, or could not run, and what it said"
196
-
197
- reference_to ModelCheckRun
198
- attribute :refusal, Report
199
-
200
- sets :refusal
201
-
202
- emits ModelCheckFlagged
203
- end
204
-
205
- # `hecks model_check` answers once the request is recorded, so the verdict is read here.
206
- query "Verdict" do
207
- description "What one check found: its status, and the report or the reason it could not run."
208
- attribute :run, RunKey
209
- where(run: :run)
210
- order_by :run
211
- end
212
-
213
- query "Flagged" do
214
- description "Every check that left a finding or could not run."
215
- where(status: "flagged")
216
- order_by :run
217
- end
218
- end
219
-
220
- policy "AnalyseWhenRequested" do
221
- on "ModelCheckRun.ModelCheckRequested"
222
- trigger ModelCheckRun::DomainRuntime::Check, with: { run: :run }
223
- end
224
-
225
- policy "RecordTheClean" do
226
- on "ModelCheckRun.ModelCheckAnswered"
227
- trigger ModelCheckRun::Pass, with: { report: :report, checked: :checked }
228
- end
229
-
230
- policy "RecordTheFlag" do
231
- on "ModelCheckRun.ModelCheckRefused"
232
- trigger ModelCheckRun::Flag, with: { refusal: :refusal }
233
- end
2
+ # Custodian: operating a domain, in the Operations module (ADR 0096). Each aggregate here is a
3
+ # concern a client runs against a domain that is running (ADR 0080, section 2); the tooling for
4
+ # building one is in tooling.bluebook.
234
5
 
235
6
  aggregate "Operation" do
236
7
  description "One thing an operator ran against a domain, and how it ended."
@@ -321,6 +92,7 @@ Hecks.bluebook "Hecks" do
321
92
  end
322
93
 
323
94
  lifecycle :status, default: "requested" do
95
+ mark :failure, "failed"
324
96
  transition "Succeed" => "succeeded", from: "requested"
325
97
  transition "Fail" => "failed", from: "requested"
326
98
  end
@@ -615,6 +387,7 @@ Hecks.bluebook "Hecks" do
615
387
  end
616
388
 
617
389
  lifecycle :status, default: "requested" do
390
+ mark :failure, "drifted", "unreachable"
618
391
  transition "Recheck" => "requested", from: %w[observed drifted unreachable]
619
392
  transition "Observe" => "observed", from: "requested"
620
393
  transition "Drift" => "drifted", from: "requested"
@@ -835,6 +608,7 @@ policy "RecordTheEra" do
835
608
  end
836
609
 
837
610
  lifecycle :status, default: "requested" do
611
+ mark :failure, "refused"
838
612
  transition "Permit" => "admitted", from: "requested"
839
613
  transition "Settle" => "settled", from: "admitted"
840
614
  transition "Abandon" => "refused", from: %w[requested admitted]
@@ -1204,999 +978,4 @@ policy "RecordTheEra" do
1204
978
  trigger Era::Abandon, with: { refusal: :refusal }
1205
979
  end
1206
980
 
1207
- aggregate "Package" do
1208
- description "One package of the bluebook registry, vendored into a project and pinned."
1209
-
1210
- attribute :package, PackageRef
1211
- attribute :from, Location, optional: true
1212
- attribute :root, Location, optional: true
1213
- attribute :report, Report, optional: true
1214
- attribute :refusal, Report, optional: true
1215
- identified_by :package
1216
-
1217
- # `name` for the newest release, `name@1.2.0` for one release, `name@9f2c1ab` for a commit.
1218
- value_object "PackageRef" do
1219
- attribute :value, String, pattern: '^[a-z][a-z0-9_]*(@[^ \t\n\r]+)?$'
1220
-
1221
- invariant("a package is named") { !value.to_s.empty? }
1222
- end
1223
-
1224
- # A directory: the source repository (`from`), or the project the files land in (`root`).
1225
- value_object "Location" do
1226
- attribute :value, String, pattern: '[^\t\n\r]'
1227
- end
1228
-
1229
- value_object "Report" do
1230
- attribute :value, String
1231
- end
1232
-
1233
- # An answer that is one document of text, exactly as the tool that produced it wrote it.
1234
- value_object "Document" do
1235
- attribute :text, String
1236
- end
1237
-
1238
- lifecycle :status, default: "requested" do
1239
- transition "Revendor" => "requested", from: %w[vendored refused]
1240
- transition "Complete" => "vendored", from: "requested"
1241
- transition "Abandon" => "refused", from: "requested"
1242
- end
1243
-
1244
- # `hecks vendor <package[@version]> [from=path] [root=path]`. The record is named by what was
1245
- # asked for, so a release is one record; vendoring the same spelling again is `hecks revendor`.
1246
- # `from` defaults to $EMBRYONAUT_BLUEBOOKS_SRC and `root` to the current directory, both read by
1247
- # the adapter.
1248
- command "Vendor" do
1249
- role "Operator"
1250
- goal "Pin a package of the bluebook registry into this project, at a release or a commit"
1251
-
1252
- attribute :package, PackageRef
1253
- attribute :from, Location, optional: true
1254
- attribute :root, Location, optional: true
1255
-
1256
- sets :package
1257
- sets :from
1258
- sets :root
1259
-
1260
- emits VendorRequested
1261
- end
1262
-
1263
- command "Revendor" do
1264
- role "Operator"
1265
- goal "Pin a package that was vendored before again, for the newest release or the same one"
1266
-
1267
- reference_to Package
1268
- attribute :from, Location, optional: true
1269
- attribute :root, Location, optional: true
1270
-
1271
- sets :from
1272
- sets :root
1273
-
1274
- emits RevendorRequested
1275
- end
1276
-
1277
- command "Complete" do
1278
- role "System"
1279
- goal "Record that the package was pinned, and what changed"
1280
-
1281
- reference_to Package
1282
- attribute :report, Report
1283
-
1284
- sets :report
1285
-
1286
- emits PackageVendored
1287
- end
1288
-
1289
- command "Abandon" do
1290
- role "System"
1291
- goal "Record that the package could not be pinned, and why"
1292
-
1293
- reference_to Package
1294
- attribute :refusal, Report
1295
-
1296
- sets :refusal
1297
-
1298
- emits VendoringRefused
1299
- end
1300
-
1301
- query "Pinning" do
1302
- description "What vendoring one package did: its status, and the report or the refusal."
1303
- attribute :package, PackageRef
1304
- where(package: :package)
1305
- order_by :package
1306
- end
1307
-
1308
- query "Unpinned" do
1309
- description "Every package the last vendoring of which was refused."
1310
- where(status: "refused")
1311
- order_by :package
1312
- end
1313
-
1314
- # `hecks package.verify [root=path]`: a read of the files, so it keeps no record. The manifest
1315
- # is the answer; a package that disagrees with its lock refuses it, naming each one.
1316
- query "Verify" do
1317
- description "Check every vendored package against its bluebook.lock, then describe them as the manifest a client image carries."
1318
- attribute :root, Location, optional: true
1319
- returns Document
1320
- end
1321
- end
1322
-
1323
- policy "PinWhenVendored" do
1324
- on "Package.VendorRequested"
1325
- trigger Package::Git::Pin, with: { package: :package }
1326
- end
1327
-
1328
- policy "PinWhenRevendored" do
1329
- on "Package.RevendorRequested"
1330
- trigger Package::Git::Pin, with: { package: :package }
1331
- end
1332
-
1333
- policy "RecordThePinning" do
1334
- on "Package.PackagePinned"
1335
- trigger Package::Complete, with: { report: :report }
1336
- end
1337
-
1338
- policy "RecordTheRefusedPin" do
1339
- on "Package.PinRefused"
1340
- trigger Package::Abandon, with: { refusal: :refusal }
1341
- end
1342
-
1343
- aggregate "Registry" do
1344
- description "A bluebook registry repository: packages versioned in it and released as tags."
1345
-
1346
- attribute :run, RegistryKey
1347
- attribute :package, PackageName, optional: true
1348
- attribute :root, Location, optional: true
1349
- attribute :report, Report, optional: true
1350
- attribute :refusal, Report, optional: true
1351
- identified_by :run
1352
-
1353
- value_object "RegistryKey" do
1354
- attribute :value, String, pattern: '[^ \t\n\r]'
1355
-
1356
- invariant("a release is named") { !value.to_s.empty? }
1357
- end
1358
-
1359
- value_object "PackageName" do
1360
- attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
1361
- end
1362
-
1363
- # The registry repository: the current directory when absent.
1364
- value_object "Location" do
1365
- attribute :value, String, pattern: '[^\t\n\r]'
1366
- end
1367
-
1368
- value_object "Report" do
1369
- attribute :value, String
1370
- end
1371
-
1372
- # An answer that is one document of text, exactly as the tool that produced it wrote it.
1373
- value_object "Document" do
1374
- attribute :text, String
1375
- end
1376
-
1377
- lifecycle :status, default: "requested" do
1378
- transition "Complete" => "tagged", from: "requested"
1379
- transition "Abandon" => "refused", from: "requested"
1380
- end
1381
-
1382
- # `hecks package.release <package> [root=path]`. Tags the package's current version as
1383
- # `<package>-vX.Y.Z` in the local repository and never pushes; the report ends in the command
1384
- # that does. A refusal says which rule the package broke.
1385
- command "Release" do
1386
- role "Operator"
1387
- goal "Tag a package of this registry at the version its bluebook.yml carries"
1388
-
1389
- attribute :run, RegistryKey
1390
- attribute :package, PackageName
1391
- attribute :root, Location, optional: true
1392
-
1393
- sets :run
1394
- sets :package
1395
- sets :root
1396
-
1397
- emits ReleaseRequested
1398
- end
1399
-
1400
- command "Complete" do
1401
- role "System"
1402
- goal "Record that the release was tagged, and the command that publishes it"
1403
-
1404
- reference_to Registry
1405
- attribute :report, Report
1406
-
1407
- sets :report
1408
-
1409
- emits ReleaseRecorded
1410
- end
1411
-
1412
- command "Abandon" do
1413
- role "System"
1414
- goal "Record that the release was refused, and why"
1415
-
1416
- reference_to Registry
1417
- attribute :refusal, Report
1418
-
1419
- sets :refusal
1420
-
1421
- emits ReleaseAbandoned
1422
- end
1423
-
1424
- # `hecks package.check [root=path]`: a read of the repository's files and tags, so it keeps no
1425
- # record. A package that changed since its latest release without a version bump and a changelog
1426
- # entry refuses it, naming each one.
1427
- query "Check" do
1428
- description "Judge every package against its latest release: a changed package needs a newer version and a changelog entry."
1429
- attribute :root, Location, optional: true
1430
- returns Document
1431
- end
1432
-
1433
- # `hecks package.digest <package> [root=path]`: a read of the package's files, so it keeps no
1434
- # record. The digest is `Lock.digest_of` over `<package>/bluebook/*.bluebook` only (the
1435
- # `bluebook.lock` digest line), then the package's shape labels; `root` is the registry, or a
1436
- # project that vendors the package.
1437
- query "Digest" do
1438
- description "Print a package's content digest and shape labels, as its bluebook.lock records them."
1439
- attribute :package, PackageName
1440
- attribute :root, Location, optional: true
1441
- returns Document
1442
- end
1443
-
1444
- query "Releasing" do
1445
- description "What releasing one run did: its status, and the report or the refusal."
1446
- attribute :run, RegistryKey
1447
- where(run: :run)
1448
- order_by :run
1449
- end
1450
-
1451
- query "Refused" do
1452
- description "Every release that was refused."
1453
- where(status: "refused")
1454
- order_by :run
1455
- end
1456
- end
1457
-
1458
- policy "TagWhenReleased" do
1459
- on "Registry.ReleaseRequested"
1460
- trigger Registry::Git::Tag, with: { run: :run }
1461
- end
1462
-
1463
- policy "RecordTheTag" do
1464
- on "Registry.ReleaseTagged"
1465
- trigger Registry::Complete, with: { report: :report }
1466
- end
1467
-
1468
- policy "RecordTheRefusedTag" do
1469
- on "Registry.ReleaseRefused"
1470
- trigger Registry::Abandon, with: { refusal: :refusal }
1471
- end
1472
-
1473
- # A run record for opening a door onto the framework, not a door: the doors live in `Hecks::Doors`.
1474
- aggregate "Door" do
1475
- description "A way into the framework opened for a project: its launchers, or an MCP server."
1476
-
1477
- attribute :run, DoorKey
1478
- attribute :domains, DomainList, optional: true
1479
- attribute :stdio, Switch, optional: true
1480
- attribute :name, DomainName, optional: true
1481
- attribute :adapter, AdapterName, optional: true
1482
- attribute :dir, TargetDir, optional: true
1483
- attribute :expert, ExpertName, optional: true
1484
- attribute :no_ai, Switch, optional: true
1485
- attribute :output, Note, optional: true
1486
- attribute :refusal, Note, optional: true
1487
- identified_by :run
1488
-
1489
- value_object "DoorKey" do
1490
- attribute :value, String, pattern: '[^ \t\n\r]'
1491
-
1492
- invariant("a door is named") { !value.to_s.empty? }
1493
- end
1494
-
1495
- # Domain directories under the project, comma separated.
1496
- value_object "DomainList" do
1497
- attribute :value, String, pattern: '[^\t\n\r]'
1498
- end
1499
-
1500
- value_object "Switch" do
1501
- attribute :value, Boolean
1502
- end
1503
-
1504
- # What a new domain is called, as its bluebook spells it: a capital and then letters and digits.
1505
- value_object "DomainName" do
1506
- attribute :value, String, pattern: '[A-Z][A-Za-z0-9]*'
1507
- end
1508
-
1509
- # A persistence adapter a stub can be bound to; `Hecks::CLI::DomainStub` names the ones it knows.
1510
- value_object "AdapterName" do
1511
- attribute :value, String, pattern: '[A-Za-z]+'
1512
- end
1513
-
1514
- # Where the new domain goes; the domain's snake-cased name under the current directory when absent.
1515
- value_object "TargetDir" do
1516
- attribute :value, String, pattern: '[^\t\n\r]'
1517
- end
1518
-
1519
- # Who is interviewed; asked for at the terminal when absent.
1520
- value_object "ExpertName" do
1521
- attribute :value, String, pattern: '[^\t\n\r]'
1522
- end
1523
-
1524
- value_object "Note" do
1525
- attribute :value, String
1526
- end
1527
-
1528
- lifecycle :status, default: "requested" do
1529
- transition "Finish" => "finished", from: "requested"
1530
- transition "Stop" => "stopped", from: "requested"
1531
- end
1532
-
1533
- # Writes a launcher beside each domain. It replaces the generated launcher already there and
1534
- # deletes nothing, so it runs without `confirm` (`hecks project_cli` never asked for one).
1535
- command "ProjectCli" do
1536
- role "Operator"
1537
- goal "Write a command-line launcher beside each domain of this project"
1538
-
1539
- attribute :run, DoorKey
1540
- attribute :domains, DomainList, optional: true
1541
-
1542
- sets :run
1543
- sets :domains
1544
-
1545
- emits LaunchersRequested
1546
- end
1547
-
1548
- # Writes the stub files of a new domain (ADR 0087). It asks nothing and replaces nothing: a
1549
- # directory that already holds any file it would write is refused, with that file named.
1550
- command "Init" do
1551
- role "Operator"
1552
- goal "Write the stub files of a new domain"
1553
-
1554
- attribute :run, DoorKey
1555
- attribute :name, DomainName
1556
- attribute :adapter, AdapterName, optional: true
1557
- attribute :dir, TargetDir, optional: true
1558
-
1559
- sets :run
1560
- sets :name
1561
- sets :adapter
1562
- sets :dir
1563
-
1564
- emits StubRequested
1565
- end
1566
-
1567
- # Holds an interview with a subject matter expert and drafts a first domain from it (ADR 0088).
1568
- # The Terminal adapter runs the conversation, as it runs a console; the journal records that one
1569
- # was held and how it ended, not what was said. `--no-ai` leaves the model out.
1570
- command "Interview" do
1571
- role "Operator"
1572
- goal "Hold an interview with a subject matter expert and draft a first domain from it"
1573
-
1574
- attribute :run, DoorKey
1575
- attribute :name, DomainName
1576
- attribute :adapter, AdapterName, optional: true
1577
- attribute :dir, TargetDir, optional: true
1578
- attribute :expert, ExpertName, optional: true
1579
- attribute :no_ai, Switch, optional: true
1580
-
1581
- sets :run
1582
- sets :name
1583
- sets :adapter
1584
- sets :dir
1585
- sets :expert
1586
- sets :no_ai
1587
-
1588
- emits InterviewRequested
1589
- end
1590
-
1591
- # A stdio server runs until its client closes stdin, so it cannot be asked and answered
1592
- # quickly like the others. The command records that the door was started; the Terminal
1593
- # adapter hands the process over to the door and answers when it closes, as OpenConsole
1594
- # does for a console. The launcher spells it `serve_mcp`; the `mcp` spelling exe/hecks ships
1595
- # today stays with its router until the launcher is generated.
1596
- command "ServeMcp" do
1597
- role "Operator"
1598
- goal "Serve the storehouse bus to an MCP client over stdio until it closes"
1599
-
1600
- attribute :run, DoorKey
1601
- attribute :stdio, Switch, optional: true
1602
-
1603
- sets :run
1604
- sets :stdio
1605
-
1606
- emits McpRequested
1607
- end
1608
-
1609
- command "Finish" do
1610
- role "System"
1611
- goal "Record that the door did its work, or was closed, and what it said"
1612
-
1613
- reference_to Door
1614
- attribute :output, Note
1615
-
1616
- sets :output
1617
-
1618
- emits DoorFinished
1619
- end
1620
-
1621
- command "Stop" do
1622
- role "System"
1623
- goal "Record that the door could not be opened, and why"
1624
-
1625
- reference_to Door
1626
- attribute :refusal, Note
1627
-
1628
- sets :refusal
1629
-
1630
- emits DoorStopped
1631
- end
1632
-
1633
- query "Ended" do
1634
- description "How one door ended: its status, and what it said or why it stopped."
1635
- attribute :run, DoorKey
1636
- where(run: :run)
1637
- order_by :run
1638
- end
1639
-
1640
- query "Stopped" do
1641
- description "Every door that could not be opened."
1642
- where(status: "stopped")
1643
- order_by :run
1644
- end
1645
- end
1646
-
1647
- policy "WriteWhenRequested" do
1648
- on "Door.LaunchersRequested"
1649
- trigger Door::Workspace::Write, with: { run: :run }
1650
- end
1651
-
1652
- policy "ScaffoldWhenRequested" do
1653
- on "Door.StubRequested"
1654
- trigger Door::Workspace::Scaffold, with: { run: :run }
1655
- end
1656
-
1657
- policy "ConverseWhenRequested" do
1658
- on "Door.InterviewRequested"
1659
- trigger Door::Terminal::Converse, with: { run: :run }
1660
- end
1661
-
1662
- policy "ServeWhenRequested" do
1663
- on "Door.McpRequested"
1664
- trigger Door::Terminal::Serve, with: { run: :run }
1665
- end
1666
-
1667
- policy "RecordTheDoor" do
1668
- on "Door.DoorAnswered"
1669
- trigger Door::Finish, with: { output: :output }
1670
- end
1671
-
1672
- policy "RecordTheStoppedDoor" do
1673
- on "Door.DoorRefused"
1674
- trigger Door::Stop, with: { refusal: :refusal }
1675
- end
1676
-
1677
- aggregate "Build" do
1678
- description "One build of a domain for the Rust host, or a check of that build against Ruby."
1679
-
1680
- attribute :run, BuildKey
1681
- attribute :domain, DomainPath, optional: true
1682
- attribute :script, ScriptPath, optional: true
1683
- attribute :artifact, Artifact, optional: true
1684
- attribute :target, TargetTriple, optional: true
1685
- attribute :stage_dir, StagePath, optional: true
1686
- attribute :seeds, Count, optional: true
1687
- attribute :steps, Count, optional: true
1688
- attribute :output, Report, optional: true
1689
- attribute :refusal, Report, optional: true
1690
- identified_by :run
1691
-
1692
- value_object "BuildKey" do
1693
- attribute :value, String, pattern: '[^ \t\n\r]'
1694
-
1695
- invariant("a build is named") { !value.to_s.empty? }
1696
- end
1697
-
1698
- # A domain directory. Its last part is also a Rust module and a Cargo feature, so it is a
1699
- # lowercase identifier; the toolchain refuses the reserved words the pattern cannot.
1700
- value_object "DomainPath" do
1701
- attribute :value, String, pattern: '(^|/)[a-z][a-z0-9_]*/?$'
1702
- end
1703
-
1704
- # A generated module: the directory name a domain was built as.
1705
- value_object "ModuleName" do
1706
- attribute :value, String, pattern: '^[a-z][a-z0-9_]*$'
1707
- end
1708
-
1709
- # A JSON file of steps for a domain to replay.
1710
- value_object "ScriptPath" do
1711
- attribute :value, String, pattern: '[^\t\n\r]'
1712
- end
1713
-
1714
- # What a build is replayed through: `native`, `build` (the domain's own feature), a `.wasm`
1715
- # module, or a binary.
1716
- value_object "Artifact" do
1717
- attribute :value, String, pattern: '[^ \t\n\r]'
1718
- end
1719
-
1720
- # A Rust target triple: `<arch>-<vendor>-<os>` with an optional `-<env>`. The toolchain
1721
- # refuses the triples a host cannot be built for (a wasm target) and the ones not installed.
1722
- value_object "TargetTriple" do
1723
- attribute :value, String, pattern: '^[a-z0-9_]+(-[a-z0-9_.]+){2,3}$'
1724
- end
1725
-
1726
- # The directory a host build stages its files in.
1727
- value_object "StagePath" do
1728
- attribute :value, String, pattern: '[^\t\n\r]'
1729
- end
1730
-
1731
- value_object "Count" do
1732
- attribute :value, Integer
1733
-
1734
- invariant("a count is positive") { value > 0 }
1735
- end
1736
-
1737
- value_object "CodegenName" do
1738
- attribute :value, String, pattern: '^(ruby|rust)$'
1739
- end
1740
-
1741
- value_object "Report" do
1742
- attribute :value, String
1743
- end
1744
-
1745
- lifecycle :status, default: "requested" do
1746
- transition "Complete" => "completed", from: "requested"
1747
- transition "Fault" => "faulted", from: "requested"
1748
- end
1749
-
1750
- # Writes the domain's Rust source and a Cargo feature for it into the build workspace: the
1751
- # checkout's own `rust/`, or a copy of the packaged workspace under `.hecks/rust/<version>/`.
1752
- # Nothing is ever written into the installed gem.
1753
- command "ProjectRust" do
1754
- role "Operator"
1755
- goal "Generate a domain's Rust source for the Rust host"
1756
-
1757
- attribute :domain, DomainPath
1758
- attribute :run, BuildKey
1759
-
1760
- sets :domain
1761
- sets :run
1762
-
1763
- emits RustProjectionRequested
1764
- end
1765
-
1766
- command "BuildWasm" do
1767
- role "Operator"
1768
- goal "Compile a domain to a WASI module a runtime such as wasmtime can run"
1769
-
1770
- attribute :domain, DomainPath
1771
- attribute :run, BuildKey
1772
-
1773
- sets :domain
1774
- sets :run
1775
-
1776
- emits WasmBuildRequested
1777
- end
1778
-
1779
- # Compiles the host binary from the installed gem's workspace for the target and stages it with
1780
- # the domain's `.wasm` and `.ir.json` (in `.hecks/host/<target>/` unless `stage_dir` names a
1781
- # directory), the files a container image copies in.
1782
- command "BuildHost" do
1783
- role "Operator"
1784
- goal "Build the Rust host for a domain, with its wasm and IR, ready to copy into an image"
1785
-
1786
- attribute :domain, DomainPath
1787
- attribute :run, BuildKey
1788
- attribute :target, TargetTriple, optional: true
1789
- attribute :stage_dir, StagePath, optional: true
1790
-
1791
- sets :domain
1792
- sets :run
1793
- sets :target
1794
- sets :stage_dir
1795
-
1796
- emits HostBuildRequested
1797
- end
1798
-
1799
- command "BuildBrowserWasm" do
1800
- role "Operator"
1801
- goal "Compile a domain to an ES module a browser can import"
1802
-
1803
- attribute :domain, DomainPath
1804
- attribute :run, BuildKey
1805
-
1806
- sets :domain
1807
- sets :run
1808
-
1809
- emits BrowserWasmBuildRequested
1810
- end
1811
-
1812
- # Without an artifact it answers Ruby's own result, which saved to a file becomes a pinned
1813
- # expectation; with one it compares Ruby's result with that artifact's.
1814
- command "CheckConformance" do
1815
- role "Operator"
1816
- goal "Replay a script through Ruby and a Rust build of the domain and compare what each did"
1817
-
1818
- attribute :domain, DomainPath
1819
- attribute :script, ScriptPath
1820
- attribute :run, BuildKey
1821
- attribute :artifact, Artifact, optional: true
1822
-
1823
- sets :domain
1824
- sets :script
1825
- sets :run
1826
- sets :artifact
1827
-
1828
- emits ConformanceRequested
1829
- end
1830
-
1831
- command "FuzzConformance" do
1832
- role "Operator"
1833
- goal "Replay generated sequences through Ruby and a Rust build of the domain and compare them"
1834
-
1835
- attribute :domain, DomainPath
1836
- attribute :artifact, Artifact
1837
- attribute :run, BuildKey
1838
- attribute :seeds, Count, optional: true
1839
- attribute :steps, Count, optional: true
1840
-
1841
- sets :domain
1842
- sets :artifact
1843
- sets :run
1844
- sets :seeds
1845
- sets :steps
1846
-
1847
- emits ConformanceFuzzRequested
1848
- end
1849
-
1850
- command "CheckCoverageAllowlist" do
1851
- role "Operator"
1852
- goal "Check that every rule excusing a Rust coverage gap still excuses a real one"
1853
-
1854
- attribute :run, BuildKey
1855
-
1856
- sets :run
1857
-
1858
- emits CoverageAllowlistRequested
1859
- end
1860
-
1861
- command "Complete" do
1862
- role "System"
1863
- goal "Record that the build or check ended well, and what it reported"
1864
-
1865
- reference_to Build
1866
- attribute :output, Report
1867
-
1868
- sets :output
1869
-
1870
- emits BuildCompleted
1871
- end
1872
-
1873
- command "Fault" do
1874
- role "System"
1875
- goal "Record that the build or check was refused or found a difference, and what it said"
1876
-
1877
- reference_to Build
1878
- attribute :refusal, Report
1879
-
1880
- sets :refusal
1881
-
1882
- emits BuildFaulted
1883
- end
1884
-
1885
- query "Result" do
1886
- description "How one build or check ended: its status, and what it reported or why it failed."
1887
- attribute :run, BuildKey
1888
- where(run: :run)
1889
- order_by :run
1890
- end
1891
-
1892
- query "Faulted" do
1893
- description "Every build or check that was refused or found a difference."
1894
- where(status: "faulted")
1895
- order_by :run
1896
- end
1897
-
1898
- # An answer that is one document of text, exactly as the tool that produced it wrote it.
1899
- value_object "Document" do
1900
- attribute :text, String
1901
- end
1902
-
1903
- query "RustCoverage" do
1904
- description "Whether each construct of a generated module has a routed Rust implementation."
1905
- attribute :module_name, ModuleName
1906
- attribute :codegen, CodegenName, optional: true
1907
- returns Document
1908
- end
1909
- end
1910
-
1911
- policy "GenerateWhenRequested" do
1912
- on "Build.RustProjectionRequested"
1913
- trigger Build::RustToolchain::Generate, with: { run: :run }
1914
- end
1915
-
1916
- policy "CompileWasmWhenRequested" do
1917
- on "Build.WasmBuildRequested"
1918
- trigger Build::RustToolchain::Wasm, with: { run: :run }
1919
- end
1920
-
1921
- policy "BuildHostWhenRequested" do
1922
- on "Build.HostBuildRequested"
1923
- trigger Build::RustToolchain::Host, with: { run: :run }
1924
- end
1925
-
1926
- policy "CompileBrowserWasmWhenRequested" do
1927
- on "Build.BrowserWasmBuildRequested"
1928
- trigger Build::RustToolchain::BrowserWasm, with: { run: :run }
1929
- end
1930
-
1931
- policy "ConformWhenRequested" do
1932
- on "Build.ConformanceRequested"
1933
- trigger Build::RustToolchain::Conform, with: { run: :run }
1934
- end
1935
-
1936
- policy "ReplayWhenRequested" do
1937
- on "Build.ConformanceFuzzRequested"
1938
- trigger Build::RustToolchain::Replay, with: { run: :run }
1939
- end
1940
-
1941
- policy "AuditWhenRequested" do
1942
- on "Build.CoverageAllowlistRequested"
1943
- trigger Build::RustToolchain::Audit, with: { run: :run }
1944
- end
1945
-
1946
- policy "RecordTheBuild" do
1947
- on "Build.BuildAnswered"
1948
- trigger Build::Complete, with: { output: :output }
1949
- end
1950
-
1951
- policy "RecordTheFault" do
1952
- on "Build.BuildRefused"
1953
- trigger Build::Fault, with: { refusal: :refusal }
1954
- end
1955
-
1956
- # Named for the run, as ModelCheckRun is: `Hecks::Fuzzing` is the fuzzing toolkit's own module,
1957
- # so a hecksagon could not spell an aggregate of that name.
1958
- aggregate "FuzzRun" do
1959
- description "One fuzz sweep or benchmark, and how it ended; and the generated sequences it replays."
1960
-
1961
- attribute :domain, DomainPath, optional: true
1962
- attribute :run, FuzzKey
1963
- attribute :seeds, Count, optional: true
1964
- attribute :steps, Count, optional: true
1965
- attribute :workers, Count, optional: true
1966
- attribute :budget, Count, optional: true
1967
- attribute :adapter, Persistence, optional: true
1968
- attribute :persist_regressions, RegressionSwitch, optional: true
1969
- attribute :domains, NameList, optional: true
1970
- attribute :targets, NameList, optional: true
1971
- attribute :iterations, Count, optional: true
1972
- attribute :warmup, Warmup, optional: true
1973
- attribute :runs, Count, optional: true
1974
- attribute :rust_binary, BinaryPath, optional: true
1975
- attribute :format, Format, optional: true
1976
- attribute :output, OutputPath, optional: true
1977
- attribute :report, Report, optional: true
1978
- attribute :refusal, Report, optional: true
1979
- identified_by :run
1980
-
1981
- value_object "FuzzKey" do
1982
- attribute :value, String, pattern: '[^ \t\n\r]'
1983
-
1984
- invariant("a sweep is named") { !value.to_s.empty? }
1985
- end
1986
-
1987
- # A domain directory; a sweep with none covers every domain of a hecks checkout.
1988
- value_object "DomainPath" do
1989
- attribute :value, String, pattern: '[^\t\n\r]'
1990
-
1991
- invariant("a domain is named by its path") { !value.to_s.empty? }
1992
- end
1993
-
1994
- value_object "Count" do
1995
- attribute :value, Integer
1996
-
1997
- invariant("a count is positive") { value > 0 }
1998
- end
1999
-
2000
- value_object "Warmup" do
2001
- attribute :value, Integer
2002
-
2003
- invariant("a warmup is not negative") { value >= 0 }
2004
- end
2005
-
2006
- # Which persistence every ephemeral boot of a sweep uses.
2007
- value_object "Persistence" do
2008
- attribute :value, String, pattern: '^(memory|sqlite|postgres)$'
2009
- end
2010
-
2011
- # Whether each distinct finding's minimized repro is also kept under `spec/corpus/regressions/`.
2012
- value_object "RegressionSwitch" do
2013
- attribute :value, Boolean
2014
- end
2015
-
2016
- # Names, comma separated: benchmark domains, or the targets to measure.
2017
- value_object "NameList" do
2018
- attribute :value, String, pattern: '^[^ \t\n\r,]+(,[^ \t\n\r,]+)*$'
2019
- end
2020
-
2021
- value_object "BinaryPath" do
2022
- attribute :value, String, pattern: '[^\t\n\r]'
2023
- end
2024
-
2025
- value_object "Format" do
2026
- attribute :value, String, pattern: '^(markdown|json)$'
2027
- end
2028
-
2029
- value_object "OutputPath" do
2030
- attribute :value, String, pattern: '[^\t\n\r]'
2031
- end
2032
-
2033
- value_object "Report" do
2034
- attribute :value, String
2035
- end
2036
-
2037
- lifecycle :status, default: "requested" do
2038
- transition "Conclude" => "concluded", from: "requested"
2039
- transition "Halt" => "halted", from: "requested"
2040
- end
2041
-
2042
- # A sweep replays generated command and query sequences and checks properties over each.
2043
- # A finding is shrunk and saved under `tmp/fuzz-failures/`, and ends the run as halted, with
2044
- # what was found. Sweeping every domain of a checkout needs a hecks checkout; a client names
2045
- # the domain. The sweep runs in child processes started through the ProcessPool adapter, so an
2046
- # interrupt reaches the workers.
2047
- command "Fuzz" do
2048
- role "Operator"
2049
- goal "Fuzz a domain with generated sequences and keep whether anything broke a property"
2050
-
2051
- attribute :domain, DomainPath, optional: true
2052
- attribute :run, FuzzKey
2053
- attribute :seeds, Count, optional: true
2054
- attribute :steps, Count, optional: true
2055
- attribute :workers, Count, optional: true
2056
- attribute :adapter, Persistence, optional: true
2057
- attribute :persist_regressions, RegressionSwitch, optional: true
2058
-
2059
- sets :domain
2060
- sets :run
2061
- sets :seeds
2062
- sets :steps
2063
- sets :workers
2064
- sets :adapter
2065
- sets :persist_regressions
2066
-
2067
- emits FuzzRequested
2068
- end
2069
-
2070
- # Mutation-tests a domain's own checks: changes its bluebooks in small ways and keeps which
2071
- # changes the fuzz properties, the corpus script and the domain's behaviors tests let through.
2072
- # A survivor is a hole in those checks. `budget` caps how many mutants are tried. The run is a
2073
- # child process started through the ProcessPool adapter, as a sweep is.
2074
- command "Mutate" do
2075
- role "Operator"
2076
- goal "Mutate a domain's rules and keep whether its checks noticed each change"
2077
-
2078
- attribute :domain, DomainPath
2079
- attribute :run, FuzzKey
2080
- attribute :seeds, Count, optional: true
2081
- attribute :steps, Count, optional: true
2082
- attribute :budget, Count, optional: true
2083
-
2084
- sets :domain
2085
- sets :run
2086
- sets :seeds
2087
- sets :steps
2088
- sets :budget
2089
-
2090
- emits MutateRequested
2091
- end
2092
-
2093
- # Measures each persistence adapter, and the Rust binary when there is one to build or use.
2094
- # The report is kept in this record, which the Hecks domain binds to Memory: keeping a
2095
- # domain's benchmark history beside it, in Sqlite under the project's `.hecks/`, is decided
2096
- # with the persistence binding for Custodian, not here. `output` also writes the full JSON.
2097
- command "Bench" do
2098
- role "Operator"
2099
- goal "Measure command throughput and latency for each target, and keep the report"
2100
-
2101
- attribute :run, FuzzKey
2102
- attribute :domains, NameList, optional: true
2103
- attribute :targets, NameList, optional: true
2104
- attribute :iterations, Count, optional: true
2105
- attribute :warmup, Warmup, optional: true
2106
- attribute :runs, Count, optional: true
2107
- attribute :rust_binary, BinaryPath, optional: true
2108
- attribute :format, Format, optional: true
2109
- attribute :output, OutputPath, optional: true
2110
-
2111
- sets :run
2112
- sets :domains
2113
- sets :targets
2114
- sets :iterations
2115
- sets :warmup
2116
- sets :runs
2117
- sets :rust_binary
2118
- sets :format
2119
- sets :output
2120
-
2121
- emits BenchRequested
2122
- end
2123
-
2124
- command "Conclude" do
2125
- role "System"
2126
- goal "Record that the sweep or benchmark ended well, and what it reported"
2127
-
2128
- reference_to FuzzRun
2129
- attribute :report, Report
2130
-
2131
- sets :report
2132
-
2133
- emits FuzzConcluded
2134
- end
2135
-
2136
- command "Halt" do
2137
- role "System"
2138
- goal "Record that the sweep found something or the benchmark could not run, and what it said"
2139
-
2140
- reference_to FuzzRun
2141
- attribute :refusal, Report
2142
-
2143
- sets :refusal
2144
-
2145
- emits FuzzHalted
2146
- end
2147
-
2148
- query "Conclusion" do
2149
- description "How one sweep or benchmark ended: its status, and what it reported or found."
2150
- attribute :run, FuzzKey
2151
- where(run: :run)
2152
- order_by :run
2153
- end
2154
-
2155
- query "Halted" do
2156
- description "Every sweep that found something and every benchmark that could not run."
2157
- where(status: "halted")
2158
- order_by :run
2159
- end
2160
-
2161
- # An answer that is one document of text, exactly as the tool that produced it wrote it.
2162
- value_object "Document" do
2163
- attribute :text, String
2164
- end
2165
-
2166
- # The generator `hecks fuzz` draws from, on its own: one valid dispatch sequence as a
2167
- # replayable script. `adversarial` is the fraction of steps mutated to be refused; 0 is off.
2168
- query "GenerateSequence" do
2169
- description "One generated, valid dispatch sequence for a domain, as a script `hecks run` replays."
2170
- attribute :domain, DomainPath
2171
- attribute :seed, Integer, optional: true
2172
- attribute :steps, Integer, optional: true
2173
- attribute :adversarial, Float, optional: true
2174
- returns Document
2175
- end
2176
- end
2177
-
2178
- policy "SweepWhenRequested" do
2179
- on "FuzzRun.FuzzRequested"
2180
- trigger FuzzRun::ProcessPool::Sweep, with: { run: :run }
2181
- end
2182
-
2183
- policy "MutateWhenRequested" do
2184
- on "FuzzRun.MutateRequested"
2185
- trigger FuzzRun::ProcessPool::Probe, with: { run: :run }
2186
- end
2187
-
2188
- policy "MeasureWhenRequested" do
2189
- on "FuzzRun.BenchRequested"
2190
- trigger FuzzRun::RustToolchain::Measure, with: { run: :run }
2191
- end
2192
-
2193
- policy "RecordTheSweep" do
2194
- on "FuzzRun.FuzzAnswered"
2195
- trigger FuzzRun::Conclude, with: { report: :report }
2196
- end
2197
-
2198
- policy "RecordTheFinding" do
2199
- on "FuzzRun.FuzzRefused"
2200
- trigger FuzzRun::Halt, with: { refusal: :refusal }
2201
- end
2202
981
  end