hecks 3.10.0 → 3.12.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 (542) 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 +158 -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 +70 -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/newcomer.rb +50 -0
  40. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +171 -0
  41. data/lib/hecks/adapters/driving/ruby/chapter.rb +91 -0
  42. data/lib/hecks/adapters/driving/ruby.rb +83 -0
  43. data/lib/hecks/adapters/driving/usage_cache.rb +144 -0
  44. data/lib/hecks/{doors.rb → adapters/driving.rb} +10 -6
  45. data/lib/hecks/behaviors/expectations/boot.rb +1 -1
  46. data/lib/hecks/bench/ruby_runner.rb +1 -1
  47. data/lib/hecks/bluebook/ask_resolution.rb +130 -0
  48. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +8 -2
  49. data/lib/hecks/bluebook/assembly/contracts/read_models.rb +1 -1
  50. data/lib/hecks/bluebook/assembly/contracts/rules.rb +4 -2
  51. data/lib/hecks/bluebook/assembly/contracts/structure.rb +3 -1
  52. data/lib/hecks/bluebook/assembly/marks.rb +4 -15
  53. data/lib/hecks/bluebook/assembly/scalars.rb +39 -0
  54. data/lib/hecks/bluebook/attribute.rb +1 -1
  55. data/lib/hecks/bluebook/behaviour/command.rb +13 -8
  56. data/lib/hecks/bluebook/behaviour/policy.rb +30 -0
  57. data/lib/hecks/bluebook/capabilities/attribute_values.rb +72 -0
  58. data/lib/hecks/bluebook/capabilities.rb +91 -9
  59. data/lib/hecks/bluebook/domain_port.rb +16 -4
  60. data/lib/hecks/bluebook/dsl/adapter_builder.rb +18 -6
  61. data/lib/hecks/bluebook/dsl/binding_proxy.rb +13 -0
  62. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/computed_sources.rb +98 -0
  63. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/fan_out_rows.rb +42 -0
  64. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +14 -2
  65. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +69 -3
  66. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +17 -10
  67. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +5 -0
  68. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
  69. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +8 -1
  70. data/lib/hecks/bluebook/dsl/command_builder/operands.rb +121 -0
  71. data/lib/hecks/bluebook/dsl/command_builder.rb +2 -0
  72. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +10 -1
  73. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +45 -2
  74. data/lib/hecks/bluebook/dsl/policy_builder.rb +47 -10
  75. data/lib/hecks/bluebook/dsl/rule_reference.rb +7 -4
  76. data/lib/hecks/bluebook/dsl/world_builder.rb +1 -1
  77. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +6 -0
  78. data/lib/hecks/bluebook/expression/ast_json.rb +9 -6
  79. data/lib/hecks/bluebook/expression/ast_reader.rb +14 -9
  80. data/lib/hecks/bluebook/expression/projection.json +36 -0
  81. data/lib/hecks/bluebook/expression/resolver/operations.rb +31 -0
  82. data/lib/hecks/bluebook/expression/resolver/parsing.rb +38 -5
  83. data/lib/hecks/bluebook/expression/resolver/scanning.rb +22 -5
  84. data/lib/hecks/bluebook/expression/resolver/values.rb +10 -0
  85. data/lib/hecks/bluebook/expression/resolver.rb +20 -1
  86. data/lib/hecks/bluebook/hecksagon.rb +23 -3
  87. data/lib/hecks/bluebook/lifecycle.rb +22 -3
  88. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +13 -1
  89. data/lib/hecks/bluebook/meta_validator/modes.rb +4 -1
  90. data/lib/hecks/bluebook/meta_validator/readings.rb +24 -1
  91. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +2 -1
  92. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +6 -3
  93. data/lib/hecks/bluebook/meta_validator/shapes.rb +5 -0
  94. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +1 -1
  95. data/lib/hecks/bluebook/meta_validator.rb +12 -12
  96. data/lib/hecks/bluebook/model_check/ask_checks.rb +71 -0
  97. data/lib/hecks/bluebook/model_check/policy_checks.rb +2 -1
  98. data/lib/hecks/bluebook/model_check/reference_checks.rb +70 -0
  99. data/lib/hecks/bluebook/model_check.rb +8 -2
  100. data/lib/hecks/bluebook/policy.rb +4 -2
  101. data/lib/hecks/bluebook/smoke_test.rb +1 -1
  102. data/lib/hecks/bluebook/synthesizer.rb +2 -0
  103. data/lib/hecks/bluebook.rb +2 -0
  104. data/lib/hecks/cli/command_table.rb +1 -1
  105. data/lib/hecks/cli/console.rb +2 -1
  106. data/lib/hecks/cli/document.rb +1 -1
  107. data/lib/hecks/cli/launcher_words.rb +4 -4
  108. data/lib/hecks/cli/mcp.rb +4 -4
  109. data/lib/hecks/cli/project_cli/launcher_source.rb +2 -2
  110. data/lib/hecks/cli/project_cli/templates.rb +5 -5
  111. data/lib/hecks/cli/project_cli.rb +9 -6
  112. data/lib/hecks/cli/run.rb +2 -2
  113. data/lib/hecks/cli/smoke_http/checks.rb +4 -1
  114. data/lib/hecks/cli/smoke_http/transport.rb +3 -3
  115. data/lib/hecks/cli/smoke_http.rb +3 -0
  116. data/lib/hecks/codemod.rb +5 -2
  117. data/lib/hecks/corpus/routes.rb +7 -0
  118. data/lib/hecks/corpus/rust.rb +3 -2
  119. data/lib/hecks/deploy/bluebook/deploy.bluebook +34 -4
  120. data/lib/hecks/doc/reference/rendering.rb +6 -3
  121. data/lib/hecks/forms/app/commands.rb +8 -7
  122. data/lib/hecks/forms/app/queries.rb +2 -1
  123. data/lib/hecks/forms/app.rb +1 -1
  124. data/lib/hecks/forms/record_renderer.rb +1 -1
  125. data/lib/hecks/framework/bluebook/privacy.bluebook +11 -0
  126. data/lib/hecks/fuzzing/concurrent_dispatch.rb +4 -1
  127. data/lib/hecks/fuzzing/failure_triage.rb +2 -1
  128. data/lib/hecks/fuzzing/mutation/run.rb +11 -4
  129. data/lib/hecks/fuzzing/properties/catalog.rb +6 -4
  130. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +18 -11
  131. data/lib/hecks/fuzzing/properties/guards.rb +1 -1
  132. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +1 -1
  133. data/lib/hecks/fuzzing/self_consistency.rb +6 -2
  134. data/lib/hecks/fuzzing/shrinker.rb +3 -1
  135. data/lib/hecks/fuzzing/value_generator.rb +19 -5
  136. data/lib/hecks/gate/stages.yml +33 -7
  137. data/lib/hecks/grammar/evolve.rb +1 -1
  138. data/lib/hecks/grammar/expression_operators.json +372 -0
  139. data/lib/hecks/grammar/operators.rb +3 -1
  140. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +10 -10
  141. data/lib/hecks/hecks/adapters/codebase/inspection/rubycritic.rb +35 -0
  142. data/lib/hecks/hecks/adapters/codebase/inspection.rb +104 -0
  143. data/lib/hecks/hecks/adapters/codebase/publishing.rb +2 -1
  144. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +12 -2
  145. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +2 -1
  146. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +1 -1
  147. data/lib/hecks/hecks/adapters/cost_explorer.rb +8 -5
  148. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +2 -1
  149. data/lib/hecks/hecks/adapters/finding_github.rb +13 -6
  150. data/lib/hecks/hecks/adapters/first_admin.rb +2 -2
  151. data/lib/hecks/hecks/adapters/github_rulesets.rb +6 -3
  152. data/lib/hecks/hecks/adapters/in_process_boot.rb +1 -1
  153. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +1 -1
  154. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +10 -20
  155. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +28 -5
  156. data/lib/hecks/hecks/adapters/local_files.rb +2 -2
  157. data/lib/hecks/hecks/adapters/rehearsal/audit_report.rb +107 -0
  158. data/lib/hecks/hecks/adapters/rehearsal/census.rb +71 -0
  159. data/lib/hecks/hecks/adapters/rehearsal/declaration.rb +133 -0
  160. data/lib/hecks/hecks/adapters/rehearsal/environment.rb +83 -0
  161. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +142 -0
  162. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +96 -0
  163. data/lib/hecks/hecks/adapters/rehearsal/postgres_census.rb +100 -0
  164. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +69 -0
  165. data/lib/hecks/hecks/adapters/rehearsal/postgres_store.rb +133 -0
  166. data/lib/hecks/hecks/adapters/rehearsal/rows.rb +41 -0
  167. data/lib/hecks/hecks/adapters/rehearsal/rust_audit.rb +83 -0
  168. data/lib/hecks/hecks/adapters/rehearsal/subject.rb +104 -0
  169. data/lib/hecks/hecks/adapters/rehearsal.rb +54 -0
  170. data/lib/hecks/hecks/adapters/rehearsal_store.adapter +7 -0
  171. data/lib/hecks/hecks/adapters/rehearsal_store.rb +81 -0
  172. data/lib/hecks/hecks/adapters/terminal.rb +13 -11
  173. data/lib/hecks/hecks/codebase.behaviors +13 -1
  174. data/lib/hecks/hecks/codebase.bluebook +239 -5
  175. data/lib/hecks/hecks/custodian.behaviors +24 -6
  176. data/lib/hecks/hecks/custodian.bluebook +6 -1227
  177. data/lib/hecks/hecks/deploy.behaviors +1 -1
  178. data/lib/hecks/hecks/deploy.world +1 -3
  179. data/lib/hecks/hecks/hecks.behaviors +1 -1
  180. data/lib/hecks/hecks/hecks.hecksagon +53 -18
  181. data/lib/hecks/hecks/hecks.world +13 -10
  182. data/lib/hecks/hecks/rehearsal.bluebook +477 -0
  183. data/lib/hecks/hecks/site.behaviors +1 -1
  184. data/lib/hecks/hecks/site.world +0 -1
  185. data/lib/hecks/hecks/tooling.bluebook +1238 -0
  186. data/lib/hecks/indifferent_key.rb +20 -0
  187. data/lib/hecks/language/adapter.bluebook +13 -3
  188. data/lib/hecks/language/bluebook/aggregate.bluebook +23 -0
  189. data/lib/hecks/language/bluebook/bluebook.behaviors +23 -0
  190. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -0
  191. data/lib/hecks/language/bluebook/entity.bluebook +18 -0
  192. data/lib/hecks/language/bluebook/policy.behaviors +19 -0
  193. data/lib/hecks/language/bluebook/policy.bluebook +9 -1
  194. data/lib/hecks/language/bluebook/query.bluebook +1 -1
  195. data/lib/hecks/language/bluebook/vocabulary.bluebook +63 -4
  196. data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -1
  197. data/lib/hecks/language/hecksagon/hecksagon.bluebook +22 -0
  198. data/lib/hecks/language/oidc.json +10 -0
  199. data/lib/hecks/language/port.bluebook +4 -4
  200. data/lib/hecks/literal.rb +12 -3
  201. data/lib/hecks/ports/key_vault.rb +7 -2
  202. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +21 -10
  203. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +4 -2
  204. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +2 -1
  205. data/lib/hecks/ports/persistence/repository_factory.rb +6 -3
  206. data/lib/hecks/projection_files/expression_tables.rb +7 -2
  207. data/lib/hecks/projections/deploy/box/compose.rb +6 -4
  208. data/lib/hecks/projections/deploy/box/edge.rb +62 -0
  209. data/lib/hecks/projections/deploy/box/logging.rb +99 -0
  210. data/lib/hecks/projections/deploy/box/roll_scripts.rb +16 -8
  211. data/lib/hecks/projections/deploy/box/settings/cdn.rb +40 -0
  212. data/lib/hecks/projections/deploy/box/settings/logs.rb +40 -0
  213. data/lib/hecks/projections/deploy/box/settings/patterns.rb +11 -0
  214. data/lib/hecks/projections/deploy/box/settings/types.rb +16 -1
  215. data/lib/hecks/projections/deploy/box/settings.rb +6 -2
  216. data/lib/hecks/projections/deploy/box/stack_yaml.rb +5 -2
  217. data/lib/hecks/projections/deploy/box/templates/Makefile.tmpl +16 -0
  218. data/lib/hecks/projections/deploy/box/templates/box.yaml.tmpl +8 -4
  219. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +32 -0
  220. data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +1 -1
  221. data/lib/hecks/projections/deploy/box/templates/edge.mk.tmpl +17 -0
  222. data/lib/hecks/projections/deploy/box/templates/edge.yaml.tmpl +65 -0
  223. data/lib/hecks/projections/deploy/box/templates/log-group.yaml.tmpl +12 -0
  224. data/lib/hecks/projections/deploy/box/templates/log-policy.yaml.tmpl +7 -0
  225. data/lib/hecks/projections/deploy/box/templates/render-compose-taskdef.sh.tmpl +5 -4
  226. data/lib/hecks/projections/deploy/box/templates/render-compose.sh.tmpl +5 -4
  227. data/lib/hecks/projections/deploy/box.rb +15 -3
  228. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  229. data/lib/hecks/projections/deploy/shared.rb +5 -2
  230. data/lib/hecks/projections/model/deviations.rb +2 -2
  231. data/lib/hecks/projections/model.rb +2 -2
  232. data/lib/hecks/projections/oidc.rb +13 -1
  233. data/lib/hecks/projections/shape.rb +5 -2
  234. data/lib/hecks/projections/site/cms_editor/attributes.rb +26 -6
  235. data/lib/hecks/projections/site/cms_editor/blocks.rb +157 -0
  236. data/lib/hecks/projections/site/cms_editor/checks.rb +14 -1
  237. data/lib/hecks/projections/site/cms_editor/clearing.rb +70 -0
  238. data/lib/hecks/projections/site/cms_editor/color.rb +124 -0
  239. data/lib/hecks/projections/site/cms_editor/composition.rb +42 -0
  240. data/lib/hecks/projections/site/cms_editor/destructive.rb +61 -0
  241. data/lib/hecks/projections/site/cms_editor/drafts.rb +102 -0
  242. data/lib/hecks/projections/site/cms_editor/hints.rb +74 -0
  243. data/lib/hecks/projections/site/cms_editor/icons.rb +86 -0
  244. data/lib/hecks/projections/site/cms_editor/key_kinds.rb +31 -0
  245. data/lib/hecks/projections/site/cms_editor/limits.rb +72 -0
  246. data/lib/hecks/projections/site/cms_editor/media.rb +1 -1
  247. data/lib/hecks/projections/site/cms_editor/moment.rb +34 -0
  248. data/lib/hecks/projections/site/cms_editor/palette.rb +115 -0
  249. data/lib/hecks/projections/site/cms_editor/pickers.rb +85 -0
  250. data/lib/hecks/projections/site/cms_editor/preview.rb +91 -0
  251. data/lib/hecks/projections/site/cms_editor/relations.rb +92 -0
  252. data/lib/hecks/projections/site/cms_editor/scale_checks.rb +66 -0
  253. data/lib/hecks/projections/site/cms_editor/scheduling.rb +150 -0
  254. data/lib/hecks/projections/site/cms_editor/schema.rb +96 -19
  255. data/lib/hecks/projections/site/cms_editor/setting.rb +52 -9
  256. data/lib/hecks/projections/site/cms_editor/targets.rb +86 -0
  257. data/lib/hecks/projections/site/cms_editor/templates/package.json.tmpl +18 -1
  258. data/lib/hecks/projections/site/cms_editor/templates/src/app.ts.tmpl +251 -57
  259. data/lib/hecks/projections/site/cms_editor/templates/src/assets.ts.tmpl +98 -0
  260. data/lib/hecks/projections/site/cms_editor/templates/src/auth/membership.ts.tmpl +32 -24
  261. data/lib/hecks/projections/site/cms_editor/templates/src/browser/app.css.tmpl +412 -0
  262. data/lib/hecks/projections/site/cms_editor/templates/src/browser/autosave.js.tmpl +144 -0
  263. data/lib/hecks/projections/site/cms_editor/templates/src/browser/blocks.js.tmpl +500 -0
  264. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_doc.js.tmpl +175 -0
  265. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_editor.js.tmpl +418 -0
  266. data/lib/hecks/projections/site/cms_editor/templates/src/browser/epoch.js.tmpl +61 -0
  267. data/lib/hecks/projections/site/cms_editor/templates/src/browser/forms.js.tmpl +210 -0
  268. data/lib/hecks/projections/site/cms_editor/templates/src/browser/lists.js.tmpl +40 -0
  269. data/lib/hecks/projections/site/cms_editor/templates/src/browser/main.js.tmpl +26 -0
  270. data/lib/hecks/projections/site/cms_editor/templates/src/browser/media_picker.js.tmpl +232 -0
  271. data/lib/hecks/projections/site/cms_editor/templates/src/browser/moments.js.tmpl +73 -0
  272. data/lib/hecks/projections/site/cms_editor/templates/src/browser/pickers.js.tmpl +152 -0
  273. data/lib/hecks/projections/site/cms_editor/templates/src/browser/preview.js.tmpl +98 -0
  274. data/lib/hecks/projections/site/cms_editor/templates/src/browser/shell.js.tmpl +140 -0
  275. data/lib/hecks/projections/site/cms_editor/templates/src/browser/toast.js.tmpl +66 -0
  276. data/lib/hecks/projections/site/cms_editor/templates/src/choices.ts.tmpl +99 -0
  277. data/lib/hecks/projections/site/cms_editor/templates/src/commands.ts.tmpl +78 -24
  278. data/lib/hecks/projections/site/cms_editor/templates/src/config.ts.tmpl +6 -0
  279. data/lib/hecks/projections/site/cms_editor/templates/src/flash.ts.tmpl +52 -0
  280. data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +19 -2
  281. data/lib/hecks/projections/site/cms_editor/templates/src/media/handler.ts.tmpl +31 -8
  282. data/lib/hecks/projections/site/cms_editor/templates/src/names.ts.tmpl +36 -0
  283. data/lib/hecks/projections/site/cms_editor/templates/src/schema.ts.tmpl +131 -2
  284. data/lib/hecks/projections/site/cms_editor/templates/src/ui/availability.ts.tmpl +15 -0
  285. data/lib/hecks/projections/site/cms_editor/templates/src/ui/block_list.js.tmpl +213 -0
  286. data/lib/hecks/projections/site/cms_editor/templates/src/ui/blocks.ts.tmpl +275 -0
  287. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_model.js.tmpl +8 -5
  288. data/lib/hecks/projections/site/cms_editor/templates/src/ui/detail.ts.tmpl +88 -0
  289. data/lib/hecks/projections/site/cms_editor/templates/src/ui/dialogs.ts.tmpl +43 -0
  290. data/lib/hecks/projections/site/cms_editor/templates/src/ui/fields.ts.tmpl +229 -34
  291. data/lib/hecks/projections/site/cms_editor/templates/src/ui/html.ts.tmpl +40 -81
  292. data/lib/hecks/projections/site/cms_editor/templates/src/ui/icons.ts.tmpl +15 -0
  293. data/lib/hecks/projections/site/cms_editor/templates/src/ui/input.ts.tmpl +29 -12
  294. data/lib/hecks/projections/site/cms_editor/templates/src/ui/links.ts.tmpl +100 -0
  295. data/lib/hecks/projections/site/cms_editor/templates/src/ui/moments.ts.tmpl +44 -0
  296. data/lib/hecks/projections/site/cms_editor/templates/src/ui/outline.ts.tmpl +53 -17
  297. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pages.ts.tmpl +178 -88
  298. data/lib/hecks/projections/site/cms_editor/templates/src/ui/paging.ts.tmpl +82 -0
  299. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pickers.ts.tmpl +110 -0
  300. data/lib/hecks/projections/site/cms_editor/templates/src/ui/preview.ts.tmpl +87 -0
  301. data/lib/hecks/projections/site/cms_editor/templates/src/ui/related.ts.tmpl +97 -0
  302. data/lib/hecks/projections/site/cms_editor/templates/src/ui/schedule.ts.tmpl +160 -0
  303. data/lib/hecks/projections/site/cms_editor/templates/src/ui/shell.ts.tmpl +211 -0
  304. data/lib/hecks/projections/site/cms_editor/templates/src/ui/table.ts.tmpl +151 -0
  305. data/lib/hecks/projections/site/cms_editor/templates/src/ui/theme.js.tmpl +16 -0
  306. data/lib/hecks/projections/site/cms_editor/templates/src/ui/values.ts.tmpl +69 -0
  307. data/lib/hecks/projections/site/cms_editor/templates/src/ui/words.ts.tmpl +97 -0
  308. data/lib/hecks/projections/site/cms_editor/templates/src/ui/world.ts.tmpl +35 -0
  309. data/lib/hecks/projections/site/cms_editor/templates/tsconfig.json.tmpl +2 -1
  310. data/lib/hecks/projections/site/cms_editor/theme.rb +29 -0
  311. data/lib/hecks/projections/site/cms_editor/theme_checks.rb +57 -0
  312. data/lib/hecks/projections/site/cms_editor.rb +49 -23
  313. data/lib/hecks/projections/site/role_probe.rb +2 -0
  314. data/lib/hecks/projections/site/site_root/workflow.rb +5 -0
  315. data/lib/hecks/projector/cli_audience.rb +22 -1
  316. data/lib/hecks/projector/cli_projector/listing.rb +1 -1
  317. data/lib/hecks/projector/cli_projector/option_specs.rb +1 -1
  318. data/lib/hecks/projector/cli_projector/usage.rb +15 -4
  319. data/lib/hecks/projector/docs_projector/closing.rb +1 -1
  320. data/lib/hecks/projector/docs_projector.rb +1 -1
  321. data/lib/hecks/projector/exporter/bindings.rb +40 -10
  322. data/lib/hecks/projector/exporter/capability_values.rb +55 -0
  323. data/lib/hecks/projector/narrate_projector/reactions.rb +1 -1
  324. data/lib/hecks/projector/target.rb +11 -0
  325. data/lib/hecks/projector.rb +32 -5
  326. data/lib/hecks/quality_control/adapters/github_checks.rb +12 -8
  327. data/lib/hecks/quality_control/adapters/github_issues.rb +8 -4
  328. data/lib/hecks/quality_control/cli/qa_open_pr.rb +2 -2
  329. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +1 -1
  330. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +1 -1
  331. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  332. data/lib/hecks/quality_control/quality_control.bluebook +6 -2
  333. data/lib/hecks/release/approval.rb +64 -0
  334. data/lib/hecks/router/{door.rb → aggregate_reader.rb} +5 -4
  335. data/lib/hecks/router/namespace_installer.rb +16 -16
  336. data/lib/hecks/router.rb +1 -1
  337. data/lib/hecks/runtime/best_effort.rb +22 -0
  338. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -2
  339. data/lib/hecks/runtime/command_interpreter.rb +3 -2
  340. data/lib/hecks/runtime/command_rules/emission.rb +1 -1
  341. data/lib/hecks/runtime/dispatcher.rb +4 -4
  342. data/lib/hecks/runtime/entity_element/location.rb +1 -1
  343. data/lib/hecks/runtime/event.rb +5 -0
  344. data/lib/hecks/runtime/identity.rb +7 -6
  345. data/lib/hecks/runtime/interpreting.rb +2 -1
  346. data/lib/hecks/runtime/invocation_builder.rb +1 -1
  347. data/lib/hecks/runtime/loader/boot_steps.rb +8 -5
  348. data/lib/hecks/runtime/loader.rb +10 -10
  349. data/lib/hecks/runtime/policy_interpreter/arguments.rb +7 -4
  350. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +3 -3
  351. data/lib/hecks/runtime/policy_interpreter.rb +6 -6
  352. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -1
  353. data/lib/hecks/runtime/reaction_invocation.rb +1 -1
  354. data/lib/hecks/runtime/rebuild_sweep.rb +11 -1
  355. data/lib/hecks/runtime/registry/ask_verification.rb +35 -0
  356. data/lib/hecks/runtime/registry/hecksagon_rules.rb +10 -0
  357. data/lib/hecks/runtime/registry/merging.rb +1 -1
  358. data/lib/hecks/runtime/registry/providers.rb +16 -0
  359. data/lib/hecks/runtime/registry/read_repository.rb +6 -4
  360. data/lib/hecks/runtime/registry/verification.rb +4 -1
  361. data/lib/hecks/runtime/registry/world_defaults.rb +29 -0
  362. data/lib/hecks/runtime/registry.rb +1 -1
  363. data/lib/hecks/runtime/saga_interpreter/compensation.rb +1 -1
  364. data/lib/hecks/runtime/saga_interpreter/delivery.rb +4 -4
  365. data/lib/hecks/runtime/saga_interpreter/transitions.rb +1 -1
  366. data/lib/hecks/runtime/saga_interpreter.rb +3 -3
  367. data/lib/hecks/runtime/tenant_check.rb +5 -4
  368. data/lib/hecks/runtime/value/coercion.rb +2 -2
  369. data/lib/hecks/runtime/value/validation.rb +16 -4
  370. data/lib/hecks/runtime.rb +9 -9
  371. data/lib/hecks/rust_build/host.rb +11 -4
  372. data/lib/hecks/rust_build/prebuilt_binary.rb +101 -0
  373. data/lib/hecks/rust_build/project_rust/target_ir.rb +1 -1
  374. data/lib/hecks/rust_build/wasm.rb +1 -1
  375. data/lib/hecks/rust_build/wasm_browser.rb +1 -1
  376. data/lib/hecks/rust_build.rb +11 -0
  377. data/lib/hecks/served_options.rb +53 -0
  378. data/lib/hecks/site/bluebook/site.bluebook +1 -0
  379. data/lib/hecks/storehouse/audit.rb +1 -1
  380. data/lib/hecks/storehouse/dispatching.rb +8 -6
  381. data/lib/hecks/storehouse/introspection.rb +2 -2
  382. data/lib/hecks/storehouse/querying.rb +6 -4
  383. data/lib/hecks/storehouse.rb +4 -4
  384. data/lib/hecks/tools/ci_gate_decision.rb +35 -0
  385. data/lib/hecks/tools/ci_gates.rb +20 -1
  386. data/lib/hecks/tools/comment_style/source_file.rb +4 -1
  387. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +4 -1
  388. data/lib/hecks/tools/lanes/files.rb +8 -0
  389. data/lib/hecks/tools/lanes/prebuilt_workflow.rb +81 -0
  390. data/lib/hecks/tools/lanes/rows.rb +6 -0
  391. data/lib/hecks/tools/lanes.rb +1 -0
  392. data/lib/hecks/tools/oidc_manifests.rb +4 -5
  393. data/lib/hecks/tools/regeneration_run.rb +11 -4
  394. data/lib/hecks/tools/release_only.rb +111 -0
  395. data/lib/hecks/tools/site_routes/editor_files.rb +12 -5
  396. data/lib/hecks/tools/tenant_provisioning.rb +2 -2
  397. data/lib/hecks/tools/tools_doc.rb +4 -4
  398. data/lib/hecks/version.rb +1 -1
  399. data/lib/hecks/vocabulary.rb +19 -5
  400. data/lib/hecks.rb +15 -15
  401. data/lib/rubocop/cop/hecks/env_dump.rb +69 -0
  402. data/lib/rubocop/cop/hecks/monotonic_duration.rb +53 -0
  403. data/lib/rubocop/cop/hecks/no_wall_clock_in_runtime.rb +34 -0
  404. data/lib/rubocop/cop/hecks/raw_shell_interpolation.rb +79 -0
  405. data/lib/rubocop/cop/hecks/sleep_in_spec.rb +34 -0
  406. data/lib/rubocop/cop/hecks/swallowed_rescue.rb +37 -0
  407. data/lib/rubocop/cop/hecks/symbol_string_key_mix.rb +50 -0
  408. data/lib/rubocop/cop/hecks/untyped_raise.rb +37 -0
  409. data/prebuilt/9ee54e2f0d4d6d3fe046827779b221e02de665fba911a048ae5dd8b8fbfb7d90.marshal +0 -0
  410. data/prebuilt/d74a00e996222c1d8b676d5959092effc46b4dc59e0555f3bf9554ac58e3094a.marshal +0 -0
  411. data/prebuilt/verdicts-df19f35868d3284a70f55e42dcef87ef4e65e6a678e5135f72e1f6cff4c1357b.json +1 -0
  412. data/rust/.gitignore +6 -0
  413. data/rust/Cargo.toml +6 -0
  414. data/rust/build/src/binding_pass.rs +103 -0
  415. data/rust/build/src/cargo_sync.rs +6 -0
  416. data/rust/build/src/lineage_pass.rs +3 -3
  417. data/rust/build/src/main.rs +17 -5
  418. data/rust/build/src/pipeline.rs +48 -5
  419. data/rust/build/src/seams_pass.rs +123 -0
  420. data/rust/build/src/translation_pass.rs +167 -0
  421. data/rust/codegen/src/asks.rs +103 -0
  422. data/rust/codegen/src/commands.rs +13 -8
  423. data/rust/codegen/src/constraints.rs +25 -0
  424. data/rust/codegen/src/domain_generator.rs +2 -0
  425. data/rust/codegen/src/expr_emitter.rs +13 -0
  426. data/rust/codegen/src/json_codec.rs +54 -15
  427. data/rust/codegen/src/main.rs +1 -0
  428. data/rust/codegen/src/mutations.rs +128 -3
  429. data/rust/codegen/src/queries.rs +11 -2
  430. data/rust/codegen/src/reactions.rs +1 -1
  431. data/rust/codegen/src/types.rs +166 -8
  432. data/rust/host/HECKS_RELEASE +1 -1
  433. data/rust/host/src/api.rs +4 -4
  434. data/rust/host/src/bin/validate_harness.rs +43 -0
  435. data/rust/host/src/boundary_fuzz/expr_json.rs +2 -2
  436. data/rust/host/src/boundary_fuzz/ir.rs +1 -0
  437. data/rust/host/src/boundary_fuzz/server.rs +1 -1
  438. data/rust/host/src/checkout.rs +35 -19
  439. data/rust/host/src/commerce_ir.rs +408 -2
  440. data/rust/host/src/expr_json.rs +118 -0
  441. data/rust/host/src/extension.rs +13 -1
  442. data/rust/host/src/lib.rs +1 -0
  443. data/rust/host/src/mint.rs +1 -1
  444. data/rust/host/src/payments/tests.rs +27 -1
  445. data/rust/host/src/payments.rs +12 -4
  446. data/rust/host/src/platform_signin/attack_tests.rs +1100 -0
  447. data/rust/host/src/platform_signin/config.rs +512 -0
  448. data/rust/host/src/platform_signin/cookie.rs +237 -0
  449. data/rust/host/src/platform_signin/extension.rs +190 -0
  450. data/rust/host/src/platform_signin/fetcher.rs +322 -0
  451. data/rust/host/src/platform_signin/handler.rs +251 -0
  452. data/rust/host/src/platform_signin/handler_tests.rs +554 -0
  453. data/rust/host/src/platform_signin/jti.rs +196 -0
  454. data/rust/host/src/platform_signin/jwks.rs +542 -0
  455. data/rust/host/src/platform_signin/jws.rs +249 -0
  456. data/rust/host/src/platform_signin/known_answer_tests.rs +237 -0
  457. data/rust/host/src/platform_signin/mapping_tests.rs +254 -0
  458. data/rust/host/src/platform_signin/mod.rs +75 -0
  459. data/rust/host/src/platform_signin/mode_tests.rs +382 -0
  460. data/rust/host/src/platform_signin/pages.rs +204 -0
  461. data/rust/host/src/platform_signin/query.rs +233 -0
  462. data/rust/host/src/platform_signin/session.rs +151 -0
  463. data/rust/host/src/platform_signin/settings.rs +385 -0
  464. data/rust/host/src/platform_signin/strict_json.rs +351 -0
  465. data/rust/host/src/platform_signin/test_support.rs +235 -0
  466. data/rust/host/src/platform_signin/ttl_tests.rs +94 -0
  467. data/rust/host/src/platform_signin/verify.rs +604 -0
  468. data/rust/host/src/platform_signin/wiring_support.rs +319 -0
  469. data/rust/host/src/query_step.rs +22 -4
  470. data/rust/host/src/reference_validate.rs +653 -108
  471. data/rust/host/src/resend.rs +2 -0
  472. data/rust/host/src/server.rs +19 -6
  473. data/rust/host/src/ui_schema.rs +132 -5
  474. data/rust/host/src/web/newsletter.rs +7 -8
  475. data/rust/host/src/web/newsletter_send.rs +38 -13
  476. data/rust/host/src/web/registrations.rs +229 -26
  477. data/rust/host/src/web.rs +53 -9
  478. data/rust/parser/src/emit.rs +38 -6
  479. data/rust/parser/src/expr/ast_json.rs +7 -1
  480. data/rust/parser/src/expr/resolver.rs +171 -6
  481. data/rust/parser/src/ir.rs +7 -0
  482. data/rust/parser/src/keywords.rs +24 -0
  483. data/rust/parser/src/main.rs +3 -0
  484. data/rust/parser/src/parse/aggregate.rs +2 -1
  485. data/rust/parser/src/parse/chapter.rs +2 -2
  486. data/rust/parser/src/parse/command.rs +2 -0
  487. data/rust/parser/src/parse/hecksagon.rs +5 -2
  488. data/rust/parser/src/parse/lifecycle.rs +81 -0
  489. data/rust/parser/src/parse/mod.rs +15 -1
  490. data/rust/parser/src/parse/policy.rs +13 -2
  491. data/rust/parser/src/parse/value_object.rs +34 -17
  492. data/rust/parser/src/ruby_value.rs +1 -1
  493. data/rust/src/exemplar/commands.rs +4 -4
  494. data/rust/src/exemplar/constraints.rs +1 -1
  495. data/rust/src/exemplar/json.rs +43 -1
  496. data/rust/src/kernel/cli.rs +7 -5
  497. data/rust/src/kernel/dispatch.rs +2 -2
  498. data/rust/src/kernel/dispatch_guard_tests.rs +1 -1
  499. data/rust/src/kernel/expr.rs +66 -3
  500. data/rust/src/kernel/expression_operators/arithmetic.rs +130 -5
  501. data/rust/src/kernel/expression_operators/text.rs +26 -2
  502. data/rust/src/kernel/json.rs +15 -0
  503. data/rust/src/kernel/mod.rs +1 -1
  504. data/rust/src/kernel/orchestrate.rs +54 -5
  505. data/rust/src/kernel/orchestrate_guard_tests.rs +67 -0
  506. data/rust/src/kernel/pattern.rs +60 -0
  507. data/rust/src/kernel/reference_lookup.rs +90 -7
  508. metadata +178 -38
  509. data/lib/hecks/doors/cli_door/nesting.rb +0 -34
  510. data/lib/hecks/doors/cli_door/shorthand.rb +0 -85
  511. data/lib/hecks/doors/cli_door.rb +0 -124
  512. data/lib/hecks/doors/cli_runner/answers.rb +0 -138
  513. data/lib/hecks/doors/cli_runner/resolution.rb +0 -146
  514. data/lib/hecks/doors/cli_runner/settling.rb +0 -115
  515. data/lib/hecks/doors/cli_runner/streaming.rb +0 -90
  516. data/lib/hecks/doors/cli_runner/suggestions.rb +0 -43
  517. data/lib/hecks/doors/cli_runner.rb +0 -66
  518. data/lib/hecks/doors/command_request.rb +0 -119
  519. data/lib/hecks/doors/handle.rb +0 -208
  520. data/lib/hecks/doors/json_door.rb +0 -132
  521. data/lib/hecks/doors/launcher_options.rb +0 -247
  522. data/lib/hecks/doors/mcp_door/properties.rb +0 -47
  523. data/lib/hecks/doors/mcp_door/tool_calls.rb +0 -113
  524. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +0 -51
  525. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +0 -69
  526. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +0 -97
  527. data/lib/hecks/doors/mcp_door/tool_definitions.rb +0 -15
  528. data/lib/hecks/doors/mcp_door.rb +0 -156
  529. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +0 -92
  530. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +0 -55
  531. data/lib/hecks/doors/mcp_door_scope/presenter.rb +0 -78
  532. data/lib/hecks/doors/mcp_door_scope.rb +0 -201
  533. data/lib/hecks/doors/mcp_guide_cache.rb +0 -75
  534. data/lib/hecks/doors/ruby_door/aggregate_door.rb +0 -162
  535. data/lib/hecks/doors/ruby_door/chapter.rb +0 -89
  536. data/lib/hecks/doors/ruby_door.rb +0 -80
  537. data/lib/hecks/doors/usage_cache.rb +0 -139
  538. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_widget.js.tmpl +0 -282
  539. data/lib/hecks/projections/site/cms_editor/templates/src/ui/media_picker.js.tmpl +0 -109
  540. data/prebuilt/c28d6d9db14eea3e17161e9d9c262efee30b256cf97693a7cfd552bce24b2f7f.marshal +0 -0
  541. data/prebuilt/cb375cba61ca0dbe8ddb9739c306510fe05e5f4b7a9b6955caff8224c63ea0e0.marshal +0 -0
  542. data/prebuilt/verdicts-d6d584ad43b5f3cebf88aafbbdbf024c38574acf18e06adffbc555f7786b1c2f.json +0 -1
@@ -4,6 +4,9 @@ module Hecks
4
4
  # Renders the pages themselves: a context's page word by word, and the index. Extended onto
5
5
  # `Reference`.
6
6
  module Rendering
7
+ # Raised when a page carries prose for a word the language does not declare.
8
+ class Error < RuntimeError; end
9
+
7
10
  # Renders one context's page, grouped by word (not per form) so a
8
11
  # two-form word doesn't repeat its heading and prose.
9
12
  def render_page(context, prose, path)
@@ -13,13 +16,13 @@ module Hecks
13
16
  page_markdown(context, prose[PREAMBLE].to_s.strip, sections)
14
17
  end
15
18
 
16
- # @raise [RuntimeError] when a page carries prose for a word the language does not declare
19
+ # @raise [Error] when a page carries prose for a word the language does not declare
17
20
  def refuse_orphans!(prose, words, context, path)
18
21
  orphans = prose.keys - words.keys - [PREAMBLE]
19
22
  return if orphans.empty?
20
23
 
21
- raise "#{path} carries prose for #{orphans.join(", ")}, which the language no longer " \
22
- "declares in #{context} — deleting writing is a human's decision, so decide"
24
+ raise Error, "#{path} carries prose for #{orphans.join(", ")}, which the language no longer " \
25
+ "declares in #{context} — deleting writing is a human's decision, so decide"
23
26
  end
24
27
 
25
28
  # @return [String] the page: its heading, generated lede, the hand-written preamble and the
@@ -1,13 +1,14 @@
1
1
  require "json"
2
2
  require_relative "../command_form_renderer"
3
3
  require_relative "../params"
4
- require_relative "../../doors/command_request"
5
- require_relative "../../doors/json_door"
4
+ require_relative "../../adapters/driving/command_request"
5
+ require_relative "../../adapters/driving/json"
6
6
 
7
7
  module Hecks
8
8
  module Forms
9
9
  class App
10
- # The command routes of `Forms::App`: the form, its submission, and the JSON door to the same
10
+ # The command routes of `Forms::App`: the form, its submission, and the JSON adapter to the
11
+ # same
11
12
  # dispatch.
12
13
  module Commands
13
14
  private
@@ -63,7 +64,7 @@ module Hecks
63
64
  def verb_name(domain, aggregate, verb) = "#{domain}::#{aggregate.hecks_name}.#{verb.hecks_name}"
64
65
 
65
66
  def command_envelope(command, args)
66
- Doors::CommandRequest.normalize(args, receiver: command_receiver(command), legacy_receiver: :id)
67
+ Adapters::Driving::CommandRequest.normalize(args, receiver: command_receiver(command), legacy_receiver: :id)
67
68
  end
68
69
 
69
70
  def command_receiver(command) = command.creates? ? nil : :aggregate
@@ -78,9 +79,9 @@ module Hecks
78
79
  end
79
80
 
80
81
  def submitted_json(request, command)
81
- raw = Doors::JsonDoor.parse(request.body.read)
82
- envelope = Doors::JsonDoor.command_request(raw, receiver: command_receiver(command),
83
- legacy_receiver: :id)
82
+ raw = Adapters::Driving::Json.parse(request.body.read)
83
+ envelope = Adapters::Driving::Json.command_request(raw, receiver: command_receiver(command),
84
+ legacy_receiver: :id)
84
85
  [raw, envelope]
85
86
  end
86
87
 
@@ -6,7 +6,8 @@ require_relative "../query_form_renderer"
6
6
  module Hecks
7
7
  module Forms
8
8
  class App
9
- # The query routes of `Forms::App`: the form with its results, and the JSON door to the same
9
+ # The query routes of `Forms::App`: the form with its results, and the JSON adapter to the
10
+ # same
10
11
  # query.
11
12
  module Queries
12
13
  private
@@ -87,7 +87,7 @@ module Hecks
87
87
 
88
88
  def refuse_entity_command
89
89
  raise RouteNotFound,
90
- "entity command routes are not supported by Forms; use a command door with " \
90
+ "entity command routes are not supported by Forms; use a command route with " \
91
91
  "to.aggregate and to.entity"
92
92
  end
93
93
 
@@ -5,7 +5,7 @@ require_relative "record_table"
5
5
  module Hecks
6
6
  module Forms
7
7
  # The index and show pages every aggregate gets, whether or not it declares a query.
8
- # They read the repository directly, like `AggregateDoor#all`/`#find`.
8
+ # They read the repository directly, like `AggregateModule#all`/`#find`.
9
9
  module RecordRenderer
10
10
  # Renders the page listing every record of one aggregate.
11
11
  def self.index(registry:, domain:, aggregate:)
@@ -2,6 +2,17 @@ Hecks.bluebook "Privacy" do
2
2
  vision "Which fields of a domain's own aggregates are sensitive is a fact about that domain, declared apart from it — the domain itself never spells out that one of its own attributes is PII or PHI."
3
3
  supporting
4
4
 
5
+ # What this chapter answers for every attaching domain: the boot that seeds `mark_sensitive`
6
+ # facts, the masking of a read and the cryptoshred read these verbs from here rather than
7
+ # recognising "Privacy" by name.
8
+ provides "privacy",
9
+ mark_sensitive: "Marking.Mark",
10
+ markings_for: "Marking.ForDomain"
11
+
12
+ provides "subject_keys",
13
+ key_for: "SubjectKey.ForSubject",
14
+ shred: "SubjectKey.Shred"
15
+
5
16
  # A domain never marks itself: `Mark` is a wiring-time command (role "Deployment").
6
17
  aggregate "Marking" do
7
18
  description "One attribute of one domain's own aggregate, flagged sensitive — and the role required to read it unredacted."
@@ -14,6 +14,9 @@ module Hecks
14
14
  # against a live domain, checking the outcome against a sequential oracle to catch a broken
15
15
  # cross-process lock.
16
16
  module ConcurrentDispatch
17
+ # Raised when a race's setup step crashes before the race starts.
18
+ class SetupFailure < RuntimeError; end
19
+
17
20
  extend Racing
18
21
  extend WorldCopy
19
22
 
@@ -130,7 +133,7 @@ module Hecks
130
133
  def dispatch_all!(runtime, steps)
131
134
  steps.each do |step|
132
135
  outcome = dispatch_one(runtime, step)
133
- raise "setup step #{step["verb"]} #{outcome}" if outcome.start_with?("crashed:")
136
+ raise SetupFailure, "setup step #{step["verb"]} #{outcome}" if outcome.start_with?("crashed:")
134
137
  end
135
138
  end
136
139
  end
@@ -1,6 +1,7 @@
1
1
  require "digest"
2
2
  require "fileutils"
3
3
  require "json"
4
+ require_relative "../indifferent_key"
4
5
 
5
6
  module Hecks
6
7
  module Fuzzing
@@ -20,7 +21,7 @@ module Hecks
20
21
  # @param steps [Array<Hash>] the shrunk steps that reproduce it
21
22
  # @return [String] a stable twelve-character identity
22
23
  def signature(property, message, steps)
23
- shape = steps.map { |step| step.key?("verb") ? step["verb"] : step[:verb] }
24
+ shape = steps.map { |step| IndifferentKey.read(step, "verb") }
24
25
  Digest::SHA256.hexdigest([property, normalize(message), shape].to_json)[0, 12]
25
26
  end
26
27
 
@@ -25,6 +25,12 @@ module Hecks
25
25
  # The checkout this file lives in, where a domain's corpus script is looked for.
26
26
  ROOT = File.expand_path("../../../..", __dir__)
27
27
 
28
+ # Where the runtime keeps era snapshots and archives (`.bluebook` copies of the domain as it
29
+ # was) under a domain. They are a record, not source: a mutant of one is never read back, so
30
+ # counting them drew budget from the domain's own files and made a run depend on whether the
31
+ # domain had ever been booted in this checkout.
32
+ RUNTIME_DATA = "data/".freeze
33
+
28
34
  # The knobs of a run: `seed` draws the sequences and the choice of mutants; `budget` caps
29
35
  # the mutants tried; `seeds` and `steps` size the generated sequences each mutant is
30
36
  # replayed against; `corpus` is a script to replay too (found by the domain's name when
@@ -81,11 +87,12 @@ module Hecks
81
87
  end
82
88
  end
83
89
 
84
- # @return [Hash{String => String}] each bluebook of the domain by path relative to it
90
+ # @return [Hash{String => String}] each authored bluebook of the domain, by relative path
85
91
  def bluebook_sources
86
- Dir.glob(File.join(@domain, "**", "*.bluebook")).to_h do |path|
87
- [path.delete_prefix("#{@domain}/"), File.read(path)]
88
- end
92
+ paths = Dir.glob(File.join(@domain, "**", "*.bluebook"))
93
+ relatives = paths.map { |path| path.delete_prefix("#{@domain}/") }
94
+ relatives.reject { |relative| relative.start_with?(RUNTIME_DATA) }
95
+ .to_h { |relative| [relative, File.read(File.join(@domain, relative))] }
89
96
  end
90
97
 
91
98
  # The parsed corpus script: the one asked for, else the one of this domain's name.
@@ -55,19 +55,21 @@ module Hecks
55
55
  ReadModel#any_field ReadModel#all_field],
56
56
  stored_records_satisfy_declared_invariants: %w[Aggregate#invariants Entity#invariants],
57
57
  group_by_matches_recompute: %w[ReadModel#group_by],
58
- # A runtime door, not a grammar construct — `Dispatcher#dry_run?` is not
58
+ # A runtime entry point, not a grammar construct — `Dispatcher#dry_run?` is not
59
59
  # a word a bluebook declares. Listed empty rather than omitted, so every
60
60
  # property still names what it is answerable for.
61
61
  dry_runs_leave_no_trace: [],
62
- # Another runtime door, not a grammar construct — same reasoning as
62
+ # Another runtime entry point, not a grammar construct — same reasoning as
63
63
  # dry_runs_leave_no_trace above.
64
64
  outbox_rows_match_reactions: [],
65
65
  # Reads command.mutations for :corrects ops — the same list
66
66
  # mutations_match_recompute reads, for a different question.
67
67
  corrections_reference_an_emitted_event: %w[Command#mutations],
68
68
  # Reads each logged reaction back against the policy that produced it: the event it
69
- # answers, the trigger it builds, and the domain `across` sends it to.
70
- policy_reactions_follow_declared_wiring: %w[Policy#on_event Policy#trigger_command Policy#target_domain],
69
+ # answers, the trigger it builds, and the domain `across` sends it to. An `ask` closes
70
+ # here too: boot binds it to the trigger it resolves to, which this reads as any other.
71
+ policy_reactions_follow_declared_wiring: %w[Policy#on_event Policy#trigger_command Policy#ask
72
+ Policy#target_domain],
71
73
  # model_check holds the static half of `expect_undelivered`; this is the runtime half.
72
74
  declared_undelivered_policies_stay_undelivered: %w[Policy#expect_undelivered],
73
75
  # An accepted referencing command addressed a record an earlier event created.
@@ -9,17 +9,17 @@ module Hecks
9
9
  # in the other direction).
10
10
  GUARANTEED_BY_CONSTRUCTION = {
11
11
  "Aggregate#attributes" => "every field's pattern/closed-set/type passes through Value.build's one coercion " \
12
- "door (value/coercion.rb#check_patterns, value/admission.rb) before it can exist " \
12
+ "entry point (value/coercion.rb#check_patterns, value/admission.rb) before it can exist " \
13
13
  "— a stored value that violated its own declared shape was never producible to " \
14
14
  "begin with",
15
- "Aggregate#value_objects" => "the shape being coerced above — same door, same guarantee",
15
+ "Aggregate#value_objects" => "the shape being coerced above — same entry point, same guarantee",
16
16
  # S17, ADR 0026 — saga_advances_follow_declared_handlers already walks
17
- # this list to find event_type/from_state/to_state; same door, same guarantee.
17
+ # this list to find event_type/from_state/to_state; same entry point, same guarantee.
18
18
  "ProcessManager#handlers" => "saga_advances_follow_declared_handlers already walks this list to find " \
19
- "event_type/from_state/to_state — same door, same guarantee",
19
+ "event_type/from_state/to_state — same entry point, same guarantee",
20
20
  "Aggregate#identified_by" => "CommandInterpreter's data-driven dispatch order refuses AlreadyExists " \
21
21
  "(command_interpreter.rb, command.creates?) for every creating command uniformly, " \
22
- "before a duplicate id can ever be stored — collision is refused at the door, not " \
22
+ "before a duplicate id can ever be stored — collision is refused at the entry point, not " \
23
23
  "produced and later caught",
24
24
  "Entity#identified_by" => "EntityElement.check_entity_collision (runtime/entity_element.rb, moved there " \
25
25
  "BUG#145 so both call sites share it) checks Array(current) against every part " \
@@ -33,17 +33,17 @@ module Hecks
33
33
  "(current.size + 1 can't repeat unless something remove:s from the list between " \
34
34
  "mints, which no real domain does today — see the comment on #entity_element " \
35
35
  "itself)",
36
- "Command#attributes" => "command arguments are coerced through the SAME Value.build door as any other " \
36
+ "Command#attributes" => "command arguments are coerced through the SAME Value.build entry point as any other " \
37
37
  "attribute — an accepted dispatch's own args already passed pattern/admits/invariant checks",
38
38
  "Command#emits" => "CommandRules::Emission#emit iterates command.emits ITSELF to construct every " \
39
39
  "announced Event (command_rules/emission.rb) — there is no other path to emit, so " \
40
40
  "a command can never announce a name its own declaration doesn't list",
41
- "Query#attributes" => "query arguments are coerced through the same Value.build door — same guarantee as " \
41
+ "Query#attributes" => "query arguments are coerced through the same Value.build entry point — same guarantee as " \
42
42
  "Command#attributes",
43
43
  "Query#returns" => "every row a port answers is built as the returned value object by Value.build " \
44
44
  "(QueryInterpreter#shaped) before it enters the domain — an answer of any other " \
45
45
  "shape is refused, so none can be accepted",
46
- "Entity#attributes" => "same coercion door, one level in — an entity's own attributes are Value-typed exactly " \
46
+ "Entity#attributes" => "same coercion path, one level in — an entity's own attributes are Value-typed exactly " \
47
47
  "the way an aggregate's are",
48
48
  "ValueObject#attributes" => "the shape Value.build enforces IS this declaration — the guarantee and the " \
49
49
  "feature are the same fact seen from two sides",
@@ -51,12 +51,19 @@ module Hecks
51
51
  "that pattern-checks a VO's fields — a VO whose invariant did not hold could not " \
52
52
  "finish being built",
53
53
  "ValueObject#rows" => "closed-set membership is checked in value/admission.rb, the second half of the same " \
54
- "one construction door",
54
+ "one construction entry point",
55
55
  # S17, ADR 0026 — Member is a genuine entity, so this reads Member#pairs,
56
56
  # not Member#shape. ValueObject#members is the same fact ValueObject#rows
57
57
  # counts, seen from the other side.
58
- "ValueObject#members" => "the members list IS what ValueObject#rows counts — same door, same guarantee",
59
- "Member#pairs" => "one level into ValueObject#rows — same door"
58
+ "ValueObject#members" => "the members list IS what ValueObject#rows counts — same entry point, same guarantee",
59
+ "Member#pairs" => "one level into ValueObject#rows — same entry point",
60
+ # ADR 0097. A mark reads no runtime state: LifecycleBuilder refuses at build any mark
61
+ # naming a state that is neither the default nor a transition target, so a built
62
+ # lifecycle can never carry a mark that points at a state it does not have.
63
+ "Aggregate#marks" => "LifecycleBuilder#refuse_unknown_mark_states! refuses at build a mark naming a " \
64
+ "state the lifecycle lacks — a built mark is always a subset of the lifecycle's states",
65
+ "Entity#marks" => "the same LifecycleBuilder refusal, one level in — an entity's lifecycle is built by " \
66
+ "the same builder"
60
67
  }.freeze
61
68
  end
62
69
  end
@@ -101,7 +101,7 @@ module Hecks
101
101
 
102
102
  # A command's own guard descriptions plus those of every command it delegates to.
103
103
  #
104
- # A delegating door refuses with its target's words, so both sets count. Resolved
104
+ # A delegating entry point refuses with its target's words, so both sets count. Resolved
105
105
  # against the full `bluebooks` map: a verb's domain is not always `history[:bluebook]`.
106
106
  def effective_guard_descriptions(bluebooks, verb, command)
107
107
  own = command.guard_descriptions
@@ -18,7 +18,7 @@ module Hecks
18
18
  # safe because nothing reads the live registry after this runs. Only state/memory are
19
19
  # compared: a leg whose `from:` and `to:` match legitimately re-runs.
20
20
  def check_saga_idempotency(runtime, history)
21
- interpreter = Runtime::SagaInterpreter.new(runtime.registry, door: runtime)
21
+ interpreter = Runtime::SagaInterpreter.new(runtime.registry, dispatcher: runtime)
22
22
 
23
23
  saga_groups(runtime, history).flat_map do |domain_name, process_manager, anchor, persisted|
24
24
  persisted.filter_map do |correlation, saga|
@@ -19,8 +19,12 @@ module Hecks
19
19
  module_function
20
20
 
21
21
  # Guarded like a runtime repository: these adapters bypass `RepositoryFactory.build`,
22
- # so an unguarded cold read here could skip the codec this pass exists to compare.
23
- def guarded_heki(**) = Ports::Persistence::CodecBoundary.guard!(Adapters::Heki.new(**))
22
+ # so an unguarded cold read here could skip the codec this pass exists to compare. They
23
+ # also bypass the framework's declared defaults, so each store says where its files go:
24
+ # directly under its own temporary root.
25
+ def guarded_heki(settings: {}, **)
26
+ Ports::Persistence::CodecBoundary.guard!(Adapters::Heki.new(settings: { dir: "." }.merge(settings), **))
27
+ end
24
28
 
25
29
  # Runs every check against the still-live runtime and the history `Replay.call` returns.
26
30
  #
@@ -1,3 +1,5 @@
1
+ require_relative "../indifferent_key"
2
+
1
3
  module Hecks
2
4
  module Fuzzing
3
5
  # Shrinks a failing step list to a small one that still reproduces the finding.
@@ -88,7 +90,7 @@ module Hecks
88
90
 
89
91
  # `key?` first, never `||`, which cannot tell a stored `false` from an absent key.
90
92
  def args_of(step)
91
- step.key?("args") ? step["args"] : step[:args]
93
+ IndifferentKey.read(step, "args")
92
94
  end
93
95
 
94
96
  LIST_FIELDS = %w[refusals queries dry_runs reactions].freeze
@@ -25,8 +25,10 @@ module Hecks
25
25
  # Tested against the value object's name plus the attribute's name; deliberately narrow, so
26
26
  # "amount"/"cents"/"sequence" keep the full Bignum pool.
27
27
  CLOCK_OR_COUNT_NAME_PATTERN = /clock|instant|expir|ttl|\bnow\b|timestamp|epoch|count/i
28
- # NaN and infinities are safe to generate; -0.0 covers signed zero.
29
- FLOAT_EDGE_CASES = [0.0, -0.0, -0.5, -100.25, Float::NAN, Float::INFINITY, -Float::INFINITY].freeze
28
+ # Signed zero and finite magnitudes. A sequence reaches the Rust kernel as JSON, which cannot
29
+ # write NaN or infinity, so a non-finite draw made the encoder raise before either runtime
30
+ # ran it; `Value`'s refusal of one is pinned by spec/runtime/numeric_boundary_spec.rb.
31
+ FLOAT_EDGE_CASES = [0.0, -0.0, -0.5, -100.25, 1.0e100, -1.0e100, 1.0e-100].freeze
30
32
  WORDS = %w[alpha bravo charlie delta echo foxtrot golf hotel india juliet].freeze
31
33
  CURRENCY_CODES = %w[USD EUR GBP JPY].freeze
32
34
 
@@ -78,11 +80,23 @@ module Hecks
78
80
  value_object.members.sample(random: random).to_h { |field, value| [field.to_s, value] }
79
81
  end
80
82
 
81
- # A value per declared attribute, keyed by attribute name.
83
+ # A value per declared attribute, keyed by attribute name; a list attribute is an array of
84
+ # up to three members, which is the shape its declaration asks for.
82
85
  def attribute_fields(value_object, aggregate, random:, known_ids:)
83
86
  value_object.attributes.to_h do |field|
84
- [field.name.to_s,
85
- value_for(field, aggregate, random: random, known_ids: known_ids, context: value_object.hecks_name)]
87
+ draw = -> { value_for(field, aggregate, random: random, known_ids: known_ids, context: value_object.hecks_name) }
88
+ [field.name.to_s, field.list? ? list_members(field, aggregate, random, &draw) : draw.call]
89
+ end
90
+ end
91
+
92
+ # Up to three members of a list held by a value object, each kept an object: a single-field
93
+ # member sent as its bare scalar is the one-field shorthand the list's own arguments draw.
94
+ def list_members(field, aggregate, random)
95
+ nested = Runtime::Value.value_object_for(aggregate, field.type.to_s)
96
+ sole = nested.attributes.first.name.to_s if nested && nested.attributes.size == 1
97
+ Array.new(random.rand(0..3)) do
98
+ member = yield
99
+ sole && !member.is_a?(Hash) ? { sole => member } : member
86
100
  end
87
101
  end
88
102
 
@@ -68,9 +68,9 @@ pre_push:
68
68
  blocked: rubocop found an offense.
69
69
  - &check_codegen_drift
70
70
  id: codegen_drift
71
- title: codegen drift, the committed rust/src/generated/ must match a fresh regeneration
71
+ title: codegen drift, rust/src/generated/ must match a fresh regeneration
72
72
  run: [bundle, exec, exe/hecks, regeneration_run.regenerate_corpus, --check, --wait]
73
- blocked: regenerating hits a diff, so the committed Rust is stale; run `hecks regenerate_corpus --confirm` and commit the result.
73
+ blocked: regenerating hits a diff. Only pizzas, mod.rs and Cargo.toml are committed, so run `hecks regenerate_corpus --confirm` (it also materializes the rest on a fresh checkout) and commit what it changed.
74
74
  - &check_comment_style
75
75
  id: comment_style
76
76
  title: comment style, every comment under lib/hecks against docs/COMMENT_STYLE_GUIDE.md
@@ -83,7 +83,8 @@ pre_push:
83
83
  blocked: a comment block ran past the cap; shorten it.
84
84
 
85
85
  # The checks a push of only unguarded lanes (`main`) runs in place of pre_push. The slow suite is
86
- # skipped there; the style checks are not, since an offense that lands on `main` is a red CI run.
86
+ # skipped there; the style checks are not, since an offense that lands on `main` is a red CI run,
87
+ # and neither is spec/fuzzing, which no commit hook runs any more.
87
88
  unguarded_push:
88
89
  env:
89
90
  HECKS_ENVIRONMENT: memory
@@ -91,14 +92,39 @@ unguarded_push:
91
92
  - *check_rubocop
92
93
  - *check_comment_style
93
94
  - *check_comment_blocks
95
+ - *check_fuzzing
94
96
 
95
- # The checks `.githooks/post-commit` runs after each commit. A red one is reported and never
96
- # blocks the commit; pre_push runs it again as the backstop.
97
- post_commit:
97
+ # The Rust io specs `ci-rust-io.yml` runs in its `rspec_rust_io` job, for a push that wants their
98
+ # answer first: `hecks gate_run.gate stage=rust_io --wait`. No hook or workflow runs it. It sets CI
99
+ # as the job does, so a skipped example fails here as it fails there. rust/src/generated is not
100
+ # committed, so the check materializes it first, as the job's generated-rust action does. The specs
101
+ # mutate rust/, and a stage's checks run at once, so the job's two legs run one after the other in
102
+ # a single check. spec/gate_rust_io_stage_spec.rb pins the spec lists to the workflow's matrix.
103
+ rust_io:
98
104
  env:
105
+ CI: "true"
99
106
  HECKS_ENVIRONMENT: memory
100
107
  checks:
101
- - *check_fuzzing
108
+ - id: rust_io
109
+ title: rust io specs, conformance, coercion, has_many, semantics corpus and feature exclusivity
110
+ run:
111
+ - sh
112
+ - -ec
113
+ - |
114
+ # Building the banking crate makes banking the default feature and rewrites the module
115
+ # list, both tracked. They are put back on the way out, and the check will not start over
116
+ # a person's uncommitted edits to them.
117
+ rewritten="rust/Cargo.toml rust/src/generated/mod.rs"
118
+ if [ -n "$(git status --porcelain -- $rewritten)" ]; then
119
+ echo "uncommitted changes in $rewritten; commit or discard them first" >&2
120
+ exit 1
121
+ fi
122
+ trap 'git checkout -q -- $rewritten' EXIT
123
+ env -u CARGO_TARGET_DIR bundle exec exe/hecks regeneration_run.regenerate_corpus --confirm --wait
124
+ bundle exec exe/hecks build.project_rust domain=examples/banking --wait
125
+ bundle exec rspec --tag io --profile 8 spec/rust_conformance_spec.rb spec/rust_conformance_fuzz_spec.rb spec/rust_numeric_coercion_spec.rb spec/rust_generated/has_many_spec.rb spec/semantics_corpus_spec.rb
126
+ bundle exec rspec --tag io --profile 8 spec/rust_generated/domain_feature_exclusivity_spec.rb
127
+ blocked: a Rust io spec failed, or skipped; the crate it built is under rust/target.
102
128
 
103
129
  # The checks `.github/workflows/ci-checks.yml` runs. It sets no `env`: the job's journal choice
104
130
  # (the `hecks-environment` action) reaches every check, as it reached each command before.
@@ -96,7 +96,7 @@ module Hecks
96
96
  end
97
97
  end
98
98
 
99
- # Narrow compatibility door for single-file callers; syntax_paths is normal.
99
+ # Narrow compatibility entry point for single-file callers; syntax_paths is normal.
100
100
  def syntax_path = syntax_paths.first
101
101
 
102
102
  # Resolves the file(s) a call should search or write.