hecks 3.9.1 → 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 (504) 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 +124 -2
  116. data/lib/hecks/deploy/bluebook/deploy.hecksagon +8 -0
  117. data/lib/hecks/deploy/oidc.json +16 -3
  118. data/lib/hecks/doc/reference/rendering.rb +6 -3
  119. data/lib/hecks/forms/app/commands.rb +8 -7
  120. data/lib/hecks/forms/app/queries.rb +2 -1
  121. data/lib/hecks/forms/app.rb +1 -1
  122. data/lib/hecks/forms/record_renderer.rb +1 -1
  123. data/lib/hecks/framework/bluebook/privacy.bluebook +11 -0
  124. data/lib/hecks/fuzzing/concurrent_dispatch.rb +4 -1
  125. data/lib/hecks/fuzzing/failure_triage.rb +2 -1
  126. data/lib/hecks/fuzzing/mutation/run.rb +11 -4
  127. data/lib/hecks/fuzzing/properties/catalog.rb +6 -4
  128. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +18 -11
  129. data/lib/hecks/fuzzing/properties/guards.rb +1 -1
  130. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +1 -1
  131. data/lib/hecks/fuzzing/self_consistency.rb +6 -2
  132. data/lib/hecks/fuzzing/shrinker.rb +3 -1
  133. data/lib/hecks/fuzzing/value_generator.rb +19 -5
  134. data/lib/hecks/gate/stages.yml +4 -10
  135. data/lib/hecks/grammar/evolve.rb +1 -1
  136. data/lib/hecks/grammar/expression_operators.json +372 -0
  137. data/lib/hecks/grammar/operators.rb +3 -1
  138. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +10 -10
  139. data/lib/hecks/hecks/adapters/codebase/inspection/rubycritic.rb +35 -0
  140. data/lib/hecks/hecks/adapters/codebase/inspection.rb +104 -0
  141. data/lib/hecks/hecks/adapters/codebase/publishing.rb +2 -1
  142. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +12 -2
  143. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +2 -1
  144. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +1 -1
  145. data/lib/hecks/hecks/adapters/cost_explorer.rb +8 -5
  146. data/lib/hecks/hecks/adapters/deploy_toolchain/clearing.rb +51 -0
  147. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +2 -1
  148. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +2 -0
  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 +129 -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/site_toolchain/role_prober.rb +78 -0
  173. data/lib/hecks/hecks/adapters/site_toolchain.rb +29 -4
  174. data/lib/hecks/hecks/adapters/terminal.rb +13 -11
  175. data/lib/hecks/hecks/adapters/world_clearing.rb +65 -0
  176. data/lib/hecks/hecks/codebase.behaviors +13 -1
  177. data/lib/hecks/hecks/codebase.bluebook +239 -5
  178. data/lib/hecks/hecks/custodian.behaviors +24 -6
  179. data/lib/hecks/hecks/custodian.bluebook +6 -1227
  180. data/lib/hecks/hecks/deploy.behaviors +1 -1
  181. data/lib/hecks/hecks/deploy.world +1 -3
  182. data/lib/hecks/hecks/hecks.behaviors +1 -1
  183. data/lib/hecks/hecks/hecks.hecksagon +61 -18
  184. data/lib/hecks/hecks/hecks.world +11 -10
  185. data/lib/hecks/hecks/rehearsal.bluebook +477 -0
  186. data/lib/hecks/hecks/site.behaviors +1 -1
  187. data/lib/hecks/hecks/site.world +0 -1
  188. data/lib/hecks/hecks/tooling.bluebook +1238 -0
  189. data/lib/hecks/indifferent_key.rb +20 -0
  190. data/lib/hecks/language/adapter.bluebook +13 -3
  191. data/lib/hecks/language/bluebook/aggregate.bluebook +23 -0
  192. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -0
  193. data/lib/hecks/language/bluebook/entity.bluebook +18 -0
  194. data/lib/hecks/language/bluebook/policy.bluebook +9 -1
  195. data/lib/hecks/language/bluebook/query.bluebook +1 -1
  196. data/lib/hecks/language/bluebook/vocabulary.bluebook +11 -4
  197. data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -1
  198. data/lib/hecks/language/hecksagon/hecksagon.bluebook +22 -0
  199. data/lib/hecks/language/oidc.json +10 -0
  200. data/lib/hecks/language/port.bluebook +4 -4
  201. data/lib/hecks/literal.rb +12 -3
  202. data/lib/hecks/ports/key_vault.rb +7 -2
  203. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +21 -10
  204. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +4 -2
  205. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +2 -1
  206. data/lib/hecks/ports/persistence/repository_factory.rb +6 -3
  207. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +29 -0
  208. data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +1 -1
  209. data/lib/hecks/projections/deploy/fargate/settings/tuning.rb +15 -0
  210. data/lib/hecks/projections/deploy/fargate/settings.rb +3 -1
  211. data/lib/hecks/projections/deploy/fargate/stack/readers.rb +1 -0
  212. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  213. data/lib/hecks/projections/deploy/shared.rb +5 -2
  214. data/lib/hecks/projections/deploy/templates/fargate/Makefile.tmpl +7 -4
  215. data/lib/hecks/projections/model/deviations.rb +2 -2
  216. data/lib/hecks/projections/model.rb +2 -2
  217. data/lib/hecks/projections/oidc.rb +13 -1
  218. data/lib/hecks/projections/shape.rb +5 -2
  219. data/lib/hecks/projections/site/cms_editor/attributes.rb +95 -0
  220. data/lib/hecks/projections/site/cms_editor/blocks.rb +157 -0
  221. data/lib/hecks/projections/site/cms_editor/checks.rb +77 -0
  222. data/lib/hecks/projections/site/cms_editor/clearing.rb +70 -0
  223. data/lib/hecks/projections/site/cms_editor/color.rb +124 -0
  224. data/lib/hecks/projections/site/cms_editor/composition.rb +42 -0
  225. data/lib/hecks/projections/site/cms_editor/destructive.rb +61 -0
  226. data/lib/hecks/projections/site/cms_editor/drafts.rb +102 -0
  227. data/lib/hecks/projections/site/cms_editor/hints.rb +74 -0
  228. data/lib/hecks/projections/site/cms_editor/icons.rb +86 -0
  229. data/lib/hecks/projections/site/cms_editor/key_kinds.rb +31 -0
  230. data/lib/hecks/projections/site/cms_editor/limits.rb +72 -0
  231. data/lib/hecks/projections/site/cms_editor/media.rb +85 -0
  232. data/lib/hecks/projections/site/cms_editor/moment.rb +34 -0
  233. data/lib/hecks/projections/site/cms_editor/palette.rb +115 -0
  234. data/lib/hecks/projections/site/cms_editor/pickers.rb +85 -0
  235. data/lib/hecks/projections/site/cms_editor/pretty.rb +40 -0
  236. data/lib/hecks/projections/site/cms_editor/preview.rb +91 -0
  237. data/lib/hecks/projections/site/cms_editor/relations.rb +92 -0
  238. data/lib/hecks/projections/site/cms_editor/scale_checks.rb +66 -0
  239. data/lib/hecks/projections/site/cms_editor/scheduling.rb +150 -0
  240. data/lib/hecks/projections/site/cms_editor/schema.rb +161 -0
  241. data/lib/hecks/projections/site/cms_editor/setting.rb +130 -0
  242. data/lib/hecks/projections/site/cms_editor/targets.rb +86 -0
  243. data/lib/hecks/projections/site/cms_editor/templates/package.json.tmpl +36 -0
  244. data/lib/hecks/projections/site/cms_editor/templates/src/app.ts.tmpl +370 -0
  245. data/lib/hecks/projections/site/cms_editor/templates/src/assets.ts.tmpl +98 -0
  246. data/lib/hecks/projections/site/cms_editor/templates/src/auth/membership.ts.tmpl +87 -0
  247. data/lib/hecks/projections/site/cms_editor/templates/src/auth/session.ts.tmpl +36 -0
  248. data/lib/hecks/projections/site/cms_editor/templates/src/auth/sso.ts.tmpl +20 -0
  249. data/lib/hecks/projections/site/cms_editor/templates/src/browser/app.css.tmpl +412 -0
  250. data/lib/hecks/projections/site/cms_editor/templates/src/browser/autosave.js.tmpl +144 -0
  251. data/lib/hecks/projections/site/cms_editor/templates/src/browser/blocks.js.tmpl +500 -0
  252. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_doc.js.tmpl +175 -0
  253. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_editor.js.tmpl +418 -0
  254. data/lib/hecks/projections/site/cms_editor/templates/src/browser/epoch.js.tmpl +61 -0
  255. data/lib/hecks/projections/site/cms_editor/templates/src/browser/forms.js.tmpl +210 -0
  256. data/lib/hecks/projections/site/cms_editor/templates/src/browser/lists.js.tmpl +40 -0
  257. data/lib/hecks/projections/site/cms_editor/templates/src/browser/main.js.tmpl +26 -0
  258. data/lib/hecks/projections/site/cms_editor/templates/src/browser/media_picker.js.tmpl +232 -0
  259. data/lib/hecks/projections/site/cms_editor/templates/src/browser/moments.js.tmpl +73 -0
  260. data/lib/hecks/projections/site/cms_editor/templates/src/browser/pickers.js.tmpl +152 -0
  261. data/lib/hecks/projections/site/cms_editor/templates/src/browser/preview.js.tmpl +98 -0
  262. data/lib/hecks/projections/site/cms_editor/templates/src/browser/shell.js.tmpl +140 -0
  263. data/lib/hecks/projections/site/cms_editor/templates/src/browser/toast.js.tmpl +66 -0
  264. data/lib/hecks/projections/site/cms_editor/templates/src/choices.ts.tmpl +99 -0
  265. data/lib/hecks/projections/site/cms_editor/templates/src/commands.ts.tmpl +133 -0
  266. data/lib/hecks/projections/site/cms_editor/templates/src/config.ts.tmpl +29 -0
  267. data/lib/hecks/projections/site/cms_editor/templates/src/flash.ts.tmpl +52 -0
  268. data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +43 -0
  269. data/lib/hecks/projections/site/cms_editor/templates/src/media/handler.ts.tmpl +177 -0
  270. data/lib/hecks/projections/site/cms_editor/templates/src/media/multipart.ts.tmpl +53 -0
  271. data/lib/hecks/projections/site/cms_editor/templates/src/media/sniff.ts.tmpl +94 -0
  272. data/lib/hecks/projections/site/cms_editor/templates/src/media/storage.ts.tmpl +50 -0
  273. data/lib/hecks/projections/site/cms_editor/templates/src/names.ts.tmpl +36 -0
  274. data/lib/hecks/projections/site/cms_editor/templates/src/schema.ts.tmpl +214 -0
  275. data/lib/hecks/projections/site/cms_editor/templates/src/server.ts.tmpl +65 -0
  276. data/lib/hecks/projections/site/cms_editor/templates/src/ui/availability.ts.tmpl +15 -0
  277. data/lib/hecks/projections/site/cms_editor/templates/src/ui/block_list.js.tmpl +213 -0
  278. data/lib/hecks/projections/site/cms_editor/templates/src/ui/blocks.ts.tmpl +275 -0
  279. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_model.js.tmpl +123 -0
  280. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_parse.js.tmpl +320 -0
  281. data/lib/hecks/projections/site/cms_editor/templates/src/ui/detail.ts.tmpl +88 -0
  282. data/lib/hecks/projections/site/cms_editor/templates/src/ui/dialogs.ts.tmpl +43 -0
  283. data/lib/hecks/projections/site/cms_editor/templates/src/ui/fields.ts.tmpl +275 -0
  284. data/lib/hecks/projections/site/cms_editor/templates/src/ui/html.ts.tmpl +61 -0
  285. data/lib/hecks/projections/site/cms_editor/templates/src/ui/icons.ts.tmpl +15 -0
  286. data/lib/hecks/projections/site/cms_editor/templates/src/ui/input.ts.tmpl +92 -0
  287. data/lib/hecks/projections/site/cms_editor/templates/src/ui/links.ts.tmpl +100 -0
  288. data/lib/hecks/projections/site/cms_editor/templates/src/ui/moments.ts.tmpl +44 -0
  289. data/lib/hecks/projections/site/cms_editor/templates/src/ui/outline.ts.tmpl +63 -0
  290. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pages.ts.tmpl +213 -0
  291. data/lib/hecks/projections/site/cms_editor/templates/src/ui/paging.ts.tmpl +82 -0
  292. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pickers.ts.tmpl +110 -0
  293. data/lib/hecks/projections/site/cms_editor/templates/src/ui/preview.ts.tmpl +87 -0
  294. data/lib/hecks/projections/site/cms_editor/templates/src/ui/related.ts.tmpl +97 -0
  295. data/lib/hecks/projections/site/cms_editor/templates/src/ui/schedule.ts.tmpl +160 -0
  296. data/lib/hecks/projections/site/cms_editor/templates/src/ui/shell.ts.tmpl +211 -0
  297. data/lib/hecks/projections/site/cms_editor/templates/src/ui/table.ts.tmpl +151 -0
  298. data/lib/hecks/projections/site/cms_editor/templates/src/ui/theme.js.tmpl +16 -0
  299. data/lib/hecks/projections/site/cms_editor/templates/src/ui/values.ts.tmpl +69 -0
  300. data/lib/hecks/projections/site/cms_editor/templates/src/ui/words.ts.tmpl +97 -0
  301. data/lib/hecks/projections/site/cms_editor/templates/src/ui/world.ts.tmpl +35 -0
  302. data/lib/hecks/projections/site/cms_editor/templates/tsconfig.json.tmpl +17 -0
  303. data/lib/hecks/projections/site/cms_editor/theme.rb +29 -0
  304. data/lib/hecks/projections/site/cms_editor/theme_checks.rb +57 -0
  305. data/lib/hecks/projections/site/cms_editor.rb +133 -0
  306. data/lib/hecks/projections/site/role_probe.rb +74 -0
  307. data/lib/hecks/projector/cli_audience.rb +2 -1
  308. data/lib/hecks/projector/cli_projector/listing.rb +1 -1
  309. data/lib/hecks/projector/cli_projector/option_specs.rb +1 -1
  310. data/lib/hecks/projector/docs_projector/closing.rb +1 -1
  311. data/lib/hecks/projector/docs_projector.rb +1 -1
  312. data/lib/hecks/projector/exporter/bindings.rb +40 -10
  313. data/lib/hecks/projector/exporter/capability_values.rb +55 -0
  314. data/lib/hecks/projector/narrate_projector/reactions.rb +1 -1
  315. data/lib/hecks/projector/target.rb +11 -0
  316. data/lib/hecks/projector.rb +32 -5
  317. data/lib/hecks/quality_control/adapters/github_checks.rb +12 -8
  318. data/lib/hecks/quality_control/adapters/github_issues.rb +8 -4
  319. data/lib/hecks/quality_control/cli/qa_open_pr.rb +2 -2
  320. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +1 -1
  321. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +1 -1
  322. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  323. data/lib/hecks/quality_control/quality_control.bluebook +6 -2
  324. data/lib/hecks/release/approval.rb +64 -0
  325. data/lib/hecks/router/{door.rb → aggregate_reader.rb} +5 -4
  326. data/lib/hecks/router/namespace_installer.rb +16 -16
  327. data/lib/hecks/router.rb +1 -1
  328. data/lib/hecks/runtime/best_effort.rb +22 -0
  329. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -2
  330. data/lib/hecks/runtime/command_interpreter.rb +3 -2
  331. data/lib/hecks/runtime/command_rules/emission.rb +1 -1
  332. data/lib/hecks/runtime/dispatcher.rb +4 -4
  333. data/lib/hecks/runtime/entity_element/location.rb +1 -1
  334. data/lib/hecks/runtime/event.rb +5 -0
  335. data/lib/hecks/runtime/identity.rb +7 -6
  336. data/lib/hecks/runtime/interpreting.rb +2 -1
  337. data/lib/hecks/runtime/invocation_builder.rb +1 -1
  338. data/lib/hecks/runtime/loader/boot_steps.rb +8 -5
  339. data/lib/hecks/runtime/loader.rb +10 -10
  340. data/lib/hecks/runtime/policy_interpreter/arguments.rb +7 -4
  341. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +3 -3
  342. data/lib/hecks/runtime/policy_interpreter.rb +6 -6
  343. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -1
  344. data/lib/hecks/runtime/reaction_invocation.rb +1 -1
  345. data/lib/hecks/runtime/rebuild_sweep.rb +11 -1
  346. data/lib/hecks/runtime/registry/ask_verification.rb +35 -0
  347. data/lib/hecks/runtime/registry/hecksagon_rules.rb +10 -0
  348. data/lib/hecks/runtime/registry/merging.rb +1 -1
  349. data/lib/hecks/runtime/registry/providers.rb +16 -0
  350. data/lib/hecks/runtime/registry/read_repository.rb +6 -4
  351. data/lib/hecks/runtime/registry/verification.rb +4 -1
  352. data/lib/hecks/runtime/registry/world_defaults.rb +29 -0
  353. data/lib/hecks/runtime/registry.rb +1 -1
  354. data/lib/hecks/runtime/saga_interpreter/compensation.rb +1 -1
  355. data/lib/hecks/runtime/saga_interpreter/delivery.rb +4 -4
  356. data/lib/hecks/runtime/saga_interpreter/transitions.rb +1 -1
  357. data/lib/hecks/runtime/saga_interpreter.rb +3 -3
  358. data/lib/hecks/runtime/tenant_check.rb +5 -4
  359. data/lib/hecks/runtime/value/coercion.rb +2 -2
  360. data/lib/hecks/runtime/value/validation.rb +16 -4
  361. data/lib/hecks/runtime.rb +9 -9
  362. data/lib/hecks/rust_build/project_rust/target_ir.rb +1 -1
  363. data/lib/hecks/rust_build/wasm.rb +1 -1
  364. data/lib/hecks/rust_build/wasm_browser.rb +1 -1
  365. data/lib/hecks/rust_build.rb +11 -0
  366. data/lib/hecks/served_options.rb +53 -0
  367. data/lib/hecks/site/bluebook/site.bluebook +29 -1
  368. data/lib/hecks/site/bluebook/site.ports.hecksagon +6 -0
  369. data/lib/hecks/storehouse/audit.rb +1 -1
  370. data/lib/hecks/storehouse/dispatching.rb +8 -6
  371. data/lib/hecks/storehouse/introspection.rb +2 -2
  372. data/lib/hecks/storehouse/querying.rb +6 -4
  373. data/lib/hecks/storehouse.rb +4 -4
  374. data/lib/hecks/tools/comment_style/source_file.rb +4 -1
  375. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +4 -1
  376. data/lib/hecks/tools/lanes/rows.rb +6 -0
  377. data/lib/hecks/tools/oidc_manifests.rb +4 -5
  378. data/lib/hecks/tools/regeneration_run.rb +11 -4
  379. data/lib/hecks/tools/site_routes/cli.rb +1 -1
  380. data/lib/hecks/tools/site_routes/editor_files.rb +45 -0
  381. data/lib/hecks/tools/site_routes.rb +14 -7
  382. data/lib/hecks/tools/tenant_provisioning.rb +2 -2
  383. data/lib/hecks/tools/tools_doc.rb +4 -4
  384. data/lib/hecks/version.rb +1 -1
  385. data/lib/hecks/vocabulary.rb +4 -4
  386. data/lib/hecks.rb +15 -15
  387. data/lib/rubocop/cop/hecks/env_dump.rb +69 -0
  388. data/lib/rubocop/cop/hecks/monotonic_duration.rb +53 -0
  389. data/lib/rubocop/cop/hecks/no_wall_clock_in_runtime.rb +34 -0
  390. data/lib/rubocop/cop/hecks/raw_shell_interpolation.rb +79 -0
  391. data/lib/rubocop/cop/hecks/sleep_in_spec.rb +34 -0
  392. data/lib/rubocop/cop/hecks/swallowed_rescue.rb +37 -0
  393. data/lib/rubocop/cop/hecks/symbol_string_key_mix.rb +50 -0
  394. data/lib/rubocop/cop/hecks/untyped_raise.rb +37 -0
  395. data/prebuilt/05c358d38d661a3774f813d49c66f5b68939af94432d66257a56f49ee2598994.marshal +0 -0
  396. data/prebuilt/26c40c61f09b09b11651c64668eda3ceb180f83cf2a3802d3033d2fd99ac841b.marshal +0 -0
  397. data/prebuilt/verdicts-230ac18c25abfd3d92ede032bee2661a4c2cd2773ab0cf0e2ae52546ba2f7af9.json +1 -0
  398. data/rust/.gitignore +6 -0
  399. data/rust/Cargo.toml +9 -1
  400. data/rust/build/src/binding_pass.rs +103 -0
  401. data/rust/build/src/cargo_sync.rs +6 -0
  402. data/rust/build/src/lineage_pass.rs +3 -3
  403. data/rust/build/src/main.rs +17 -5
  404. data/rust/build/src/pipeline.rs +48 -5
  405. data/rust/build/src/seams_pass.rs +123 -0
  406. data/rust/build/src/translation_pass.rs +167 -0
  407. data/rust/codegen/src/asks.rs +103 -0
  408. data/rust/codegen/src/bridging.rs +1 -1
  409. data/rust/codegen/src/commands.rs +13 -8
  410. data/rust/codegen/src/constraints.rs +25 -0
  411. data/rust/codegen/src/domain_generator.rs +11 -9
  412. data/rust/codegen/src/expr_emitter.rs +13 -0
  413. data/rust/codegen/src/json_codec.rs +54 -15
  414. data/rust/codegen/src/main.rs +2 -1
  415. data/rust/codegen/src/mutations.rs +174 -4
  416. data/rust/codegen/src/naming.rs +30 -0
  417. data/rust/codegen/src/queries.rs +11 -2
  418. data/rust/codegen/src/reactions.rs +1 -1
  419. data/rust/codegen/src/types.rs +166 -8
  420. data/rust/host/HECKS_RELEASE +1 -1
  421. data/rust/host/src/api.rs +4 -4
  422. data/rust/host/src/bin/validate_harness.rs +43 -0
  423. data/rust/host/src/boundary_fuzz/expr_json.rs +2 -2
  424. data/rust/host/src/boundary_fuzz/ir.rs +1 -0
  425. data/rust/host/src/boundary_fuzz/server.rs +1 -1
  426. data/rust/host/src/checkout.rs +35 -19
  427. data/rust/host/src/commerce_ir.rs +408 -2
  428. data/rust/host/src/expr_json.rs +118 -0
  429. data/rust/host/src/mint.rs +1 -1
  430. data/rust/host/src/payments/tests.rs +27 -1
  431. data/rust/host/src/payments.rs +12 -4
  432. data/rust/host/src/query_step.rs +22 -4
  433. data/rust/host/src/reference_validate.rs +653 -108
  434. data/rust/host/src/resend.rs +2 -0
  435. data/rust/host/src/server.rs +19 -6
  436. data/rust/host/src/ui_schema.rs +132 -5
  437. data/rust/host/src/web/newsletter.rs +7 -8
  438. data/rust/host/src/web/newsletter_send.rs +38 -13
  439. data/rust/host/src/web/registrations.rs +229 -26
  440. data/rust/host/src/web.rs +3 -3
  441. data/rust/parser/src/emit.rs +38 -6
  442. data/rust/parser/src/expr/ast_json.rs +7 -1
  443. data/rust/parser/src/expr/resolver.rs +171 -6
  444. data/rust/parser/src/ir.rs +7 -0
  445. data/rust/parser/src/keywords.rs +24 -0
  446. data/rust/parser/src/main.rs +3 -0
  447. data/rust/parser/src/parse/aggregate.rs +2 -1
  448. data/rust/parser/src/parse/chapter.rs +2 -2
  449. data/rust/parser/src/parse/command.rs +2 -0
  450. data/rust/parser/src/parse/hecksagon.rs +5 -2
  451. data/rust/parser/src/parse/lifecycle.rs +81 -0
  452. data/rust/parser/src/parse/mod.rs +15 -1
  453. data/rust/parser/src/parse/policy.rs +13 -2
  454. data/rust/parser/src/parse/value_object.rs +13 -8
  455. data/rust/parser/src/ruby_value.rs +1 -1
  456. data/rust/src/exemplar/commands.rs +4 -4
  457. data/rust/src/exemplar/constraints.rs +1 -1
  458. data/rust/src/exemplar/json.rs +43 -1
  459. data/rust/src/kernel/cli.rs +7 -5
  460. data/rust/src/kernel/dispatch.rs +2 -2
  461. data/rust/src/kernel/dispatch_guard_tests.rs +1 -1
  462. data/rust/src/kernel/expr.rs +73 -4
  463. data/rust/src/kernel/expression_operators/arithmetic.rs +130 -5
  464. data/rust/src/kernel/expression_operators/presence.rs +41 -3
  465. data/rust/src/kernel/expression_operators/text.rs +26 -2
  466. data/rust/src/kernel/json.rs +15 -0
  467. data/rust/src/kernel/mod.rs +1 -1
  468. data/rust/src/kernel/orchestrate.rs +54 -5
  469. data/rust/src/kernel/orchestrate_guard_tests.rs +67 -0
  470. data/rust/src/kernel/pattern.rs +60 -0
  471. data/rust/src/kernel/reference_lookup.rs +90 -7
  472. metadata +174 -36
  473. data/lib/hecks/doors/cli_door/nesting.rb +0 -34
  474. data/lib/hecks/doors/cli_door/shorthand.rb +0 -85
  475. data/lib/hecks/doors/cli_door.rb +0 -124
  476. data/lib/hecks/doors/cli_runner/answers.rb +0 -138
  477. data/lib/hecks/doors/cli_runner/resolution.rb +0 -146
  478. data/lib/hecks/doors/cli_runner/settling.rb +0 -115
  479. data/lib/hecks/doors/cli_runner/streaming.rb +0 -90
  480. data/lib/hecks/doors/cli_runner/suggestions.rb +0 -43
  481. data/lib/hecks/doors/cli_runner.rb +0 -66
  482. data/lib/hecks/doors/command_request.rb +0 -119
  483. data/lib/hecks/doors/handle.rb +0 -208
  484. data/lib/hecks/doors/json_door.rb +0 -132
  485. data/lib/hecks/doors/launcher_options.rb +0 -247
  486. data/lib/hecks/doors/mcp_door/properties.rb +0 -47
  487. data/lib/hecks/doors/mcp_door/tool_calls.rb +0 -113
  488. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +0 -51
  489. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +0 -69
  490. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +0 -97
  491. data/lib/hecks/doors/mcp_door/tool_definitions.rb +0 -15
  492. data/lib/hecks/doors/mcp_door.rb +0 -156
  493. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +0 -92
  494. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +0 -55
  495. data/lib/hecks/doors/mcp_door_scope/presenter.rb +0 -78
  496. data/lib/hecks/doors/mcp_door_scope.rb +0 -201
  497. data/lib/hecks/doors/mcp_guide_cache.rb +0 -75
  498. data/lib/hecks/doors/ruby_door/aggregate_door.rb +0 -162
  499. data/lib/hecks/doors/ruby_door/chapter.rb +0 -89
  500. data/lib/hecks/doors/ruby_door.rb +0 -80
  501. data/lib/hecks/doors/usage_cache.rb +0 -139
  502. data/prebuilt/0ee7f83cba59ce7d1c45c65ba166b071779f70143449f584f33ff7989f64eccb.marshal +0 -0
  503. data/prebuilt/6e4a6bcf0aa880e2e6b056e1846b70e5a768090b9dc998bbadeaf5d6bcfd3db8.marshal +0 -0
  504. data/prebuilt/verdicts-91aaf93ce8981bd9a754948f075d95650dc2ec6435015376f5c60992b36a24b1.json +0 -1
@@ -1,162 +0,0 @@
1
- require_relative "../../bluebook/dsl/hecksagon_builder"
2
- require_relative "../../bluebook/dsl/world_builder"
3
- require_relative "../../bluebook/dsl/domain_port_builder"
4
- require_relative "../../bluebook/dsl/const_shim"
5
- require_relative "../../bluebook/dsl/binding_proxy"
6
- require_relative "../../bluebook/hecksagon"
7
- require_relative "../handle"
8
- require_relative "../../naming"
9
-
10
- module Hecks
11
- module Doors
12
- module RubyDoor
13
- # One aggregate's door: creating verbs and queries as module methods, CRUD
14
- # delegation, and the `.hecksagon` binding/port hooks it lands on.
15
- module AggregateDoor
16
- # Builds one aggregate's door module: creating-command methods, query methods,
17
- # find/all/count/events, project/docs/narrate, and the port/binding hooks.
18
- #
19
- # Kept as one method: `:port`/`:method_missing`/`:const_missing` below
20
- # cross-reference each other and would lose that thread if split up.
21
- # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
22
- def aggregate_module(dispatcher, domain, aggregate)
23
- fqn = "#{domain}::#{aggregate.hecks_name}"
24
- door = Module.new
25
-
26
- aggregate.attributes.each do |attribute|
27
- next unless RESERVED.include?(attribute.name.to_sym)
28
-
29
- warn "[hecks] #{aggregate.hecks_name}##{attribute.name} shadows a built-in — no reader defined"
30
- end
31
-
32
- # `!` marks a creating command (Ruby's mutate-and-may-refuse convention).
33
- # Without it, a query sharing the same business name (e.g. Account's
34
- # "Open") would collide with the creating command's own bare name.
35
- aggregate.commands.select(&:creates?).each do |command|
36
- door.define_singleton_method("#{Naming.snake(command.hecks_name)}!") do |**args|
37
- Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate,
38
- instance: dispatcher.dispatch("#{fqn}.#{command.hecks_name}", with: args).instance)
39
- end
40
- end
41
-
42
- # A query is a bare module method (no `!`): it just reads and returns
43
- # the same raw row array `dispatcher.query` itself answers.
44
- aggregate.queries.each do |query|
45
- door.define_singleton_method(Naming.snake(query.hecks_name)) do |**args|
46
- dispatcher.query("#{fqn}.#{query.hecks_name}", **args)
47
- end
48
- end
49
-
50
- door.define_singleton_method(:fqn) { fqn }
51
- door.define_singleton_method(:ir) { aggregate }
52
-
53
- # Every construct emits its own IR, so an aggregate is a legitimate
54
- # `project` target too. A chapter-scoped target refuses here via
55
- # `Projector.admits!` rather than answering a confidently empty result.
56
- door.define_singleton_method(:project) do |target, out: nil, **options|
57
- key = Projector.key_for(target)
58
- artifact = Projector.call(key, bluebook: aggregate, options: options)
59
- return artifact unless out
60
-
61
- Projector.write(artifact, out, as: Projector.emits_for(key))
62
- end
63
- door.define_singleton_method(:repository) { dispatcher.registry.repository(domain, aggregate) }
64
- door.define_singleton_method(:commands) do
65
- aggregate.commands.map { |c| "#{Naming.snake(c.hecks_name)}!" }.sort
66
- end
67
- door.define_singleton_method(:queries) { aggregate.queries.map { |q| Naming.snake(q.hecks_name) }.sort }
68
- # This chapter's own `:docs` projection, narrowed to this aggregate.
69
- door.define_singleton_method(:docs) do |**options|
70
- Projector.call(:docs, bluebook: dispatcher.registry.bluebook(domain),
71
- options: options.merge(aggregate: aggregate.hecks_name))
72
- end
73
- # Same narrowing as `:docs`, aimed at `:narrate`.
74
- door.define_singleton_method(:narrate) do |**options|
75
- Projector.call(:narrate, bluebook: dispatcher.registry.bluebook(domain),
76
- options: options.merge(aggregate: aggregate.hecks_name))
77
- end
78
- door.define_singleton_method(:count) { dispatcher.registry.repository(domain, aggregate).count }
79
- door.define_singleton_method(:events) { dispatcher.events.select { |event| event.aggregate == fqn } }
80
-
81
- door.define_singleton_method(:find) do |id|
82
- found = dispatcher.registry.repository(domain, aggregate).find(id)
83
- found && Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate, instance: found)
84
- end
85
-
86
- door.define_singleton_method(:all) do |**opts|
87
- dispatcher.registry.repository(domain, aggregate).all(**opts).map do |instance|
88
- Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate, instance: instance)
89
- end
90
- end
91
-
92
- # Re-resolves via `Hecks.current_registry` rather than the closed-over
93
- # `aggregate`: this door can be stale from an earlier boot, and its own
94
- # `aggregate` would silently port a discarded one instead of the live one.
95
- door.define_singleton_method(:port) do |name, &block|
96
- current = Hecks.current_registry&.bluebook(domain)&.aggregate(aggregate.hecks_name) or
97
- raise Bluebook::DSL::Malformed, "#{fqn}.port(#{name.inspect}) called outside a boot"
98
-
99
- built = Bluebook::DSL::ConstShim.with(->(const) { const }) do
100
- Bluebook::DSL::DomainPortBuilder.build(name, owner: current.hecks_name, &block)
101
- end
102
-
103
- # A `verb`-shaped port is a plain `Port`, the same struct `Hecks.port` registers —
104
- # it belongs to no aggregate IR the way an operations-shaped `DomainPort` does, so
105
- # it takes the registry's `add_port` directly. Mirrors `DSL::BindingProxy#port`,
106
- # which handles the identical shape on a domain's first in-process boot (before
107
- # this facade constant exists); this method is what a repeat boot reaches instead.
108
- if built.is_a?(Bluebook::Port)
109
- Hecks.current_registry.add_port(built)
110
- return self
111
- end
112
-
113
- built.operations.each do |operation|
114
- operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = current }
115
- end
116
- current.add_port(built)
117
- self
118
- end
119
-
120
- door.define_singleton_method(:method_missing) do |verb, *args, **kwargs, &block|
121
- # A bare call starts a Privacy marking chain (see
122
- # `BindingProxy#method_missing`), reached here when the door is already
123
- # installed (a second in-process boot) rather than at parse time.
124
- return Bluebook::DSL::AttributePath.new(fqn, [verb.to_s]) if args.empty? && kwargs.empty? && !block
125
-
126
- collector = Bluebook::DSL::HecksagonBuilder.collector
127
- world = Bluebook::DSL::WorldBuilder.current
128
- # Inside a `.world` block the same qualified spelling records a world setting.
129
- return world.record_binding(verb, args, kwargs, block) if world && !collector
130
- return super(verb, *args, **kwargs, &block) unless collector
131
-
132
- collector << Bluebook::Bind.new(
133
- aggregate: fqn,
134
- verb: verb.to_s,
135
- adapter: args.first.to_s,
136
- role: kwargs[:role]&.to_s
137
- )
138
- block&.call
139
- self
140
- end
141
-
142
- door.define_singleton_method(:respond_to_missing?) do |name, include_private = false|
143
- !Bluebook::DSL::HecksagonBuilder.collector.nil? || !Bluebook::DSL::WorldBuilder.current.nil? ||
144
- super(name, include_private)
145
- end
146
-
147
- # Uses `aggregate.hecks_name`, not the qualified `fqn`: qualifying it here
148
- # would make `Account::Debit`'s meaning depend on whether a stale door
149
- # from an earlier boot happens to be sitting on this process.
150
- door.define_singleton_method(:const_missing) do |name|
151
- resolver = Bluebook::DSL::ConstShim.resolver
152
- return resolver.call("#{aggregate.hecks_name}::#{name}") if resolver
153
-
154
- super(name)
155
- end
156
-
157
- door
158
- end
159
- end
160
- end
161
- end
162
- end
@@ -1,89 +0,0 @@
1
- require_relative "../../bluebook/dsl/binding_proxy"
2
- require_relative "../../bluebook/dsl/const_shim"
3
- require_relative "../../bluebook/dsl/hecksagon_builder"
4
-
5
- module Hecks
6
- module Doors
7
- module RubyDoor
8
- # One chapter's module: vision and aggregate list on the singleton, one
9
- # aggregate door per declared head, and a `const_missing` hook for undeclared names.
10
- module Chapter
11
- # Builds the anonymous module that stands for one booted chapter: `vision`,
12
- # `aggregates`, `docs`, `narrate` and `project` as singleton methods, plus one
13
- # nested constant per aggregate holding that aggregate's door.
14
- #
15
- # @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
16
- # dispatcher each aggregate door closes over
17
- # @param bluebook [Bluebook::Chapter] the chapter to project into a module
18
- # @return [Module] a fresh, unnamed module; `RubyDoor.install` gives it its
19
- # top-level name
20
- # @raise [NameError] if an aggregate's name is not a valid constant name
21
- def chapter_module(dispatcher, bluebook)
22
- chapter = Module.new
23
- define_readers(chapter, bluebook)
24
- define_projections(chapter, bluebook)
25
-
26
- bluebook.aggregates.each do |aggregate|
27
- chapter.const_set(aggregate.hecks_name, aggregate_module(dispatcher, bluebook.name, aggregate))
28
- end
29
-
30
- define_const_missing(chapter, bluebook)
31
- chapter
32
- end
33
-
34
- private
35
-
36
- # The chapter's vision and its aggregate names.
37
- def define_readers(chapter, bluebook)
38
- chapter.define_singleton_method(:vision) { bluebook.vision }
39
- chapter.define_singleton_method(:aggregates) { bluebook.aggregates.map(&:name).sort }
40
- end
41
-
42
- # The chapter's documents and projections, each projected from its IR on every call so
43
- # none can go stale.
44
- def define_projections(chapter, bluebook)
45
- chapter.define_singleton_method(:docs) do |**options|
46
- Projector.call(:docs, bluebook: bluebook, options: options)
47
- end
48
-
49
- # The chapter read back in english, via `Projector::NarrateProjector`.
50
- chapter.define_singleton_method(:narrate) do |**options|
51
- Projector.call(:narrate, bluebook: bluebook, options: options)
52
- end
53
-
54
- define_project(chapter, bluebook)
55
- end
56
-
57
- # Projects the chapter's IR through a target; `out:` writes the artifact and
58
- # the remaining options go to the projector (`audience:` for OIDC).
59
- #
60
- # Pizzas.project(Projections::OIDC)
61
- # Pizzas.project(Projections::Shape, out: "shape.json")
62
- def define_project(chapter, bluebook)
63
- chapter.define_singleton_method(:project) do |target, out: nil, **options|
64
- key = Projector.key_for(target)
65
- artifact = Projector.call(key, bluebook: bluebook, options: options)
66
- return artifact unless out
67
-
68
- Projector.write(artifact, out, as: Projector.emits_for(key))
69
- end
70
- end
71
-
72
- # Inside a hecksagon a name is a declaration: with a collector open it becomes
73
- # a `BindingProxy`. Otherwise a scoped reference from a bluebook mid-declaration
74
- # goes to the `ConstShim` resolver, so it resolves whether or not a facade exists.
75
- def define_const_missing(chapter, bluebook)
76
- chapter.define_singleton_method(:const_missing) do |name|
77
- collector = Bluebook::DSL::HecksagonBuilder.collector
78
- return Bluebook::DSL::BindingProxy.new("#{bluebook.name}::#{name}", collector) if collector
79
-
80
- resolver = Bluebook::DSL::ConstShim.resolver
81
- return resolver.call("#{bluebook.name}::#{name}") if resolver
82
-
83
- super(name)
84
- end
85
- end
86
- end
87
- end
88
- end
89
- end
@@ -1,80 +0,0 @@
1
- require_relative "../chapters"
2
- require_relative "ruby_door/chapter"
3
- require_relative "ruby_door/aggregate_door"
4
-
5
- module Hecks
6
- module Doors
7
- # The door without classes: anonymous per-boot modules whose singleton methods
8
- # dispatch by FQN, installed by `Loader.bind_runtime` and replaced whole on the next boot.
9
- #
10
- # `persisted_by("Heki")` in a `.hecksagon` file lands on the module's `method_missing`,
11
- # which records a `Bind` into the open `HecksagonBuilder.collector`.
12
- module RubyDoor
13
- # Names that would shadow the machinery a Handle runs on; a field with one gets no reader.
14
- RESERVED = %i[id state events reload inspect to_h hash class].freeze
15
-
16
- extend Chapter
17
- extend AggregateDoor
18
-
19
- module_function
20
-
21
- # Installs one top-level module per booted chapter, and one per aggregate, each
22
- # closing over `dispatcher`, so `Pizzas::Pizza` and the bare `Pizza` both open the
23
- # door of the boot that ran last.
24
- #
25
- # A gem chapter a hecksagon `attaches` installs nothing (`Query`, `Port` stay free).
26
- # An aggregate sharing its chapter's name gets no second constant. A name that user
27
- # code or the stdlib already owns is left alone with a warning (see `Namespace.install`).
28
- #
29
- # @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
30
- # dispatcher every installed door dispatches and queries through
31
- # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the same `dispatcher`
32
- # @raise [NameError] if a chapter or aggregate name is not a valid constant name
33
- def install(dispatcher)
34
- dispatcher.registry.bluebooks.each_value do |bluebook|
35
- install_chapter(dispatcher, bluebook) unless attached_chapter?(dispatcher.registry, bluebook)
36
- end
37
- dispatcher
38
- end
39
-
40
- # Installs one chapter's module, and the top-level shortcut of each of its aggregates.
41
- def install_chapter(dispatcher, bluebook)
42
- chapter = chapter_module(dispatcher, bluebook)
43
- Namespace.install(*placement(bluebook), chapter)
44
- # A namespaced chapter keeps its aggregates inside its namespace: top-level
45
- # shortcuts would bring back the collisions the namespace exists to avoid.
46
- return if bluebook.namespace
47
-
48
- bluebook.aggregates.each do |aggregate|
49
- next if aggregate.hecks_name == bluebook.name
50
-
51
- Namespace.install(Object, aggregate.hecks_name, chapter.const_get(aggregate.hecks_name, false))
52
- end
53
- end
54
-
55
- # Whether `bluebook` is a gem chapter that a hecksagon attached rather than a domain's own.
56
- #
57
- # @param registry [Runtime::Registry] the booted registry
58
- # @param bluebook [Bluebook::Chapter] the chapter under test
59
- # @return [Boolean]
60
- def attached_chapter?(registry, bluebook)
61
- registry.bounded?(bluebook.name) && Hecks::Chapters.index.key?(bluebook.name)
62
- end
63
-
64
- # Where a chapter's module installs: `Object::<name>`, or the constant path its
65
- # `namespace` names, creating any missing parent modules along the way.
66
- #
67
- # @param bluebook [Bluebook::Chapter] the chapter being installed
68
- # @return [Array(Module, String)] the parent module and the constant name within it
69
- def placement(bluebook)
70
- return [Object, bluebook.name] unless bluebook.namespace
71
-
72
- *parents, leaf = bluebook.namespace.split("::")
73
- parent = parents.reduce(Object) do |outer, name|
74
- outer.const_defined?(name, false) ? outer.const_get(name, false) : outer.const_set(name, Module.new)
75
- end
76
- [parent, leaf]
77
- end
78
- end
79
- end
80
- end
@@ -1,139 +0,0 @@
1
- require "digest"
2
- require "fileutils"
3
- require "json"
4
-
5
- module Hecks
6
- module Doors
7
- # Remembers the help a launcher prints, so a repeat `hecks` need not read the domain again.
8
- #
9
- # The help is a pure function of the domain's declarations and of the gem that projects them,
10
- # and reading those is most of what a launcher costs. The answer is kept in a file named for a
11
- # digest of everything it depends on (the domain's declaration files, the gem's judging code and
12
- # doors, the hecks and Ruby versions, the environment overlay, the command line and the
13
- # program name),
14
- # so any edit to one of them is simply a different entry: nothing is ever stale, only unused.
15
- # Only an answer that ended well is kept, and any trouble with the cache itself is ignored
16
- # and the help is worked out as if it did not exist.
17
- #
18
- # `HECKS_NO_USAGE_CACHE=1` turns it off; `HECKS_CACHE_DIR` moves it.
19
- module UsageCache
20
- # The variable that turns the cache off when set to anything but empty or `0`.
21
- DISABLE_VARIABLE = "HECKS_NO_USAGE_CACHE".freeze
22
- # The variable that names the directory the cache lives in.
23
- DIRECTORY_VARIABLE = "HECKS_CACHE_DIR".freeze
24
- # The declaration files whose contents shape a help text.
25
- DECLARATIONS = "*.{bluebook,world,hecksagon,rb}".freeze
26
- # How long an unused entry stays before the next write sweeps it away.
27
- KEEP_SECONDS = 14 * 24 * 60 * 60
28
-
29
- module_function
30
-
31
- # Answers the cached help for this command line, or works it out with the block and
32
- # remembers it.
33
- #
34
- # @param runtime [#directory] what `Hecks.describe` answered; anything else bypasses the cache
35
- # @param argv [Array<String>] the command line
36
- # @param program [String] how the caller was invoked
37
- # @param audience [String] who the help is for, since the same line reads differently to each
38
- # @yield works the answer out, loading the domain
39
- # @yieldreturn [Array(String, Integer), nil] the text and status; nil if it runs a command
40
- # @return [Array(String, Integer), nil] the block's answer, or the remembered one
41
- def fetch(runtime, argv, program, audience: "")
42
- directory = runtime.respond_to?(:directory) ? runtime.directory : nil
43
- return yield unless directory && enabled?
44
-
45
- file = entry_path(directory, argv, program, audience)
46
- remembered = file && recall(file)
47
- return remembered if remembered
48
-
49
- answer = yield
50
- remember(file, answer) if worth_keeping?(file, answer)
51
- answer
52
- end
53
-
54
- # Whether an answer that ended well can be written to the entry's file.
55
- def worth_keeping?(file, answer)
56
- file && answer&.last&.zero?
57
- end
58
-
59
- # @return [Boolean] whether the cache is on
60
- def enabled?
61
- off = ENV[DISABLE_VARIABLE].to_s
62
- off.empty? || off == "0"
63
- end
64
-
65
- # @return [String] the directory entries live in
66
- def directory
67
- ENV[DIRECTORY_VARIABLE] || File.join(ENV["XDG_CACHE_HOME"] || File.join(Dir.home, ".cache"), "hecks")
68
- end
69
-
70
- # The file that holds the answer for this command line, named by what it depends on.
71
- #
72
- # @return [String, nil] nil when the digest cannot be taken
73
- def entry_path(domain, argv, program, audience = "")
74
- digest = Digest::SHA256.new
75
- key_parts(program, audience, argv).each { |part| digest << part.to_s << "\0" }
76
- fingerprint_code(domain, digest)
77
- File.join(directory, "usage-#{digest.hexdigest}.json")
78
- rescue SystemCallError
79
- nil
80
- end
81
-
82
- # @return [Array<String>] what the answer depends on besides the files: the gem and Ruby
83
- # series, the environment overlay, the program and audience and the command line
84
- def key_parts(program, audience, argv)
85
- [Hecks::VERSION, Hecks::Bluebook::MetaValidator::VerdictCache.ruby_series,
86
- ENV["HECKS_ENVIRONMENT"].to_s, program, audience, argv.join("\0")]
87
- end
88
-
89
- # Feeds the digest every declaration file under `root`: its path below `root` and its bytes,
90
- # so a touch or a checkout elsewhere keeps the entry and an edit does not.
91
- def fingerprint(root, digest)
92
- Dir.glob(File.join(root, "**", DECLARATIONS)).each do |file|
93
- digest << file.delete_prefix(root) << "\0" << File.binread(file) << "\0"
94
- end
95
- end
96
-
97
- # Feeds the digest what shapes a help text: the domain's declarations, the judging trees of
98
- # the gem (the same set the verdict cache keys on) and the doors that render the text. An
99
- # edit to the gem's projections, deploy or release code cannot change a help line.
100
- def fingerprint_code(domain, digest)
101
- fingerprint(domain, digest)
102
- digest << Hecks::Bluebook::MetaValidator::VerdictCache.code_digest << "\0"
103
- fingerprint(__dir__, digest)
104
- end
105
-
106
- # Reads the remembered answer and marks the entry as used, so a sweep keeps what is read.
107
- #
108
- # @return [Array(String, Integer), nil] the remembered answer, or nil when none can be trusted
109
- def recall(file)
110
- record = JSON.parse(File.read(file))
111
- File.utime(nil, nil, file)
112
- [record.fetch("text"), record.fetch("status")]
113
- rescue SystemCallError, JSON::ParserError, KeyError
114
- nil
115
- end
116
-
117
- # Writes the answer beside its name and sweeps entries nobody has read for a while.
118
- def remember(file, answer)
119
- FileUtils.mkdir_p(File.dirname(file))
120
- scratch = "#{file}.#{Process.pid}"
121
- File.write(scratch, JSON.generate("text" => answer.first, "status" => answer.last))
122
- File.rename(scratch, file)
123
- sweep(File.dirname(file))
124
- rescue SystemCallError
125
- nil
126
- end
127
-
128
- # Removes the entries older than `KEEP_SECONDS`.
129
- def sweep(dir)
130
- cutoff = Time.now - KEEP_SECONDS
131
- Dir.glob(File.join(dir, "usage-*.json")).each do |entry|
132
- File.delete(entry) if File.mtime(entry) < cutoff
133
- end
134
- rescue SystemCallError
135
- nil
136
- end
137
- end
138
- end
139
- end