hecks 2.7.0 → 2.9.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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +11 -0
  3. data/lib/hecks/adapters/driven/claude_code.rb +4 -104
  4. data/lib/hecks/adapters/driven/d1.rb +44 -237
  5. data/lib/hecks/adapters/driven/folder.rb +17 -76
  6. data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
  7. data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
  8. data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
  9. data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
  10. data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
  11. data/lib/hecks/adapters/driven/heki.rb +13 -42
  12. data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
  15. data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
  16. data/lib/hecks/adapters/driven/lambda.rb +10 -84
  17. data/lib/hecks/adapters/driven/local_storage.rb +5 -40
  18. data/lib/hecks/adapters/driven/memory.rb +18 -99
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres.rb +145 -134
  25. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  26. data/lib/hecks/adapters/driven/prism.rb +7 -30
  27. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  28. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  29. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  30. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  31. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  32. data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
  33. data/lib/hecks/adapters/driven.rb +5 -36
  34. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  35. data/lib/hecks/behaviors/dsl.rb +7 -25
  36. data/lib/hecks/behaviors/expectations.rb +32 -142
  37. data/lib/hecks/behaviors/ir.rb +7 -20
  38. data/lib/hecks/behaviors/rspec.rb +6 -17
  39. data/lib/hecks/behaviors/runner.rb +10 -34
  40. data/lib/hecks/behaviors.rb +4 -8
  41. data/lib/hecks/bluebook/aggregate.rb +9 -75
  42. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  43. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  44. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  45. data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
  46. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  47. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  48. data/lib/hecks/bluebook/assembly.rb +6 -45
  49. data/lib/hecks/bluebook/attribute.rb +12 -61
  50. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
  51. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  52. data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
  53. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  54. data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
  55. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  56. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  57. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  58. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  59. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  60. data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
  61. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  62. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  63. data/lib/hecks/bluebook/capabilities.rb +17 -49
  64. data/lib/hecks/bluebook/chapter.rb +10 -48
  65. data/lib/hecks/bluebook/command.rb +23 -81
  66. data/lib/hecks/bluebook/domain_port.rb +14 -63
  67. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  68. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  69. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  70. data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
  71. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
  72. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
  73. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
  74. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  75. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  76. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
  77. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  78. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  79. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
  80. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  81. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  82. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  83. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  84. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  85. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  86. data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
  87. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  88. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  89. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  90. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  91. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  92. data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
  93. data/lib/hecks/bluebook/entity.rb +13 -71
  94. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  95. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  96. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  97. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  98. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  99. data/lib/hecks/bluebook/expression/resolver.rb +37 -660
  100. data/lib/hecks/bluebook/hexagon.rb +5 -28
  101. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  102. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  103. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  104. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  105. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  106. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  107. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
  108. data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
  109. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
  110. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  111. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  112. data/lib/hecks/bluebook/meta_validator.rb +79 -349
  113. data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
  114. data/lib/hecks/bluebook/model_check.rb +102 -600
  115. data/lib/hecks/bluebook/pattern_subset.rb +11 -69
  116. data/lib/hecks/bluebook/process_manager.rb +13 -83
  117. data/lib/hecks/bluebook/project_loader.rb +3 -39
  118. data/lib/hecks/bluebook/project_register.rb +12 -60
  119. data/lib/hecks/bluebook/query.rb +9 -48
  120. data/lib/hecks/bluebook/read_model.rb +57 -81
  121. data/lib/hecks/bluebook/reference.rb +7 -41
  122. data/lib/hecks/bluebook/smoke_test.rb +8 -98
  123. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  124. data/lib/hecks/bluebook/translation.rb +26 -62
  125. data/lib/hecks/bluebook/value_object.rb +11 -36
  126. data/lib/hecks/bluebook.rb +5 -22
  127. data/lib/hecks/cache_dir.rb +84 -0
  128. data/lib/hecks/cli/document.rb +86 -0
  129. data/lib/hecks/cli/ir.rb +45 -0
  130. data/lib/hecks/cli/mcp.rb +31 -0
  131. data/lib/hecks/cli/mcp_door.rb +366 -0
  132. data/lib/hecks/cli/model_check.rb +203 -0
  133. data/lib/hecks/cli/project_cli.rb +90 -0
  134. data/lib/hecks/cli/project_diagrams.rb +36 -0
  135. data/lib/hecks/cli/run.rb +173 -0
  136. data/lib/hecks/cli/smoke_test.rb +45 -0
  137. data/lib/hecks/cli/stores.rb +53 -0
  138. data/lib/hecks/cli.rb +160 -0
  139. data/lib/hecks/construct.rb +8 -34
  140. data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
  141. data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
  142. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  143. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  144. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  145. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  146. data/lib/hecks/embryonaut_bluebook.rb +4 -71
  147. data/lib/hecks/facade/cli_door.rb +24 -106
  148. data/lib/hecks/facade/cli_runner.rb +28 -172
  149. data/lib/hecks/facade/command_request.rb +13 -33
  150. data/lib/hecks/facade/handle.rb +34 -121
  151. data/lib/hecks/facade/json_door.rb +31 -146
  152. data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
  153. data/lib/hecks/facade/surface/chapter.rb +10 -54
  154. data/lib/hecks/facade/surface.rb +8 -23
  155. data/lib/hecks/facade.rb +10 -25
  156. data/lib/hecks/forms/app.rb +15 -70
  157. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  158. data/lib/hecks/forms/field_renderer.rb +17 -156
  159. data/lib/hecks/forms/field_shape.rb +30 -222
  160. data/lib/hecks/forms/html.rb +12 -47
  161. data/lib/hecks/forms/index_renderer.rb +1 -4
  162. data/lib/hecks/forms/page.rb +3 -9
  163. data/lib/hecks/forms/params.rb +14 -60
  164. data/lib/hecks/forms/port_argument.rb +2 -19
  165. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  166. data/lib/hecks/forms/record_renderer.rb +8 -75
  167. data/lib/hecks/forms/record_table.rb +7 -50
  168. data/lib/hecks/forms/reference_options.rb +3 -30
  169. data/lib/hecks/forms/value_object_shape.rb +8 -35
  170. data/lib/hecks/forms.rb +5 -33
  171. data/lib/hecks/fqn.rb +5 -12
  172. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  173. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  174. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  175. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  176. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  177. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  178. data/lib/hecks/framework.rb +11 -80
  179. data/lib/hecks/freezer.rb +5 -39
  180. data/lib/hecks/grammar/expression.bluebook +15 -40
  181. data/lib/hecks/grammar/translation.bluebook +3 -6
  182. data/lib/hecks/grammar.rb +16 -41
  183. data/lib/hecks/ir.rb +14 -83
  184. data/lib/hecks/language/adapter.bluebook +2 -7
  185. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  186. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  187. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
  188. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  189. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  190. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  191. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  192. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  193. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  194. data/lib/hecks/language/bluebook/query.bluebook +12 -43
  195. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  196. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  197. data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
  198. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  199. data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
  200. data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
  201. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  202. data/lib/hecks/language/oidc.json +35 -0
  203. data/lib/hecks/language/port.bluebook +4 -17
  204. data/lib/hecks/language/translation/translation.bluebook +3 -9
  205. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  206. data/lib/hecks/language/world/wiring.bluebook +1 -3
  207. data/lib/hecks/language/world/world.bluebook +5 -7
  208. data/lib/hecks/literal.rb +8 -50
  209. data/lib/hecks/mcp_door_scope.rb +95 -0
  210. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  211. data/lib/hecks/naming.rb +29 -137
  212. data/lib/hecks/ports/access_control.rb +7 -23
  213. data/lib/hecks/ports/agent/answers.rb +5 -23
  214. data/lib/hecks/ports/agent.rb +47 -172
  215. data/lib/hecks/ports/authentication.rb +12 -39
  216. data/lib/hecks/ports/authorization.rb +16 -43
  217. data/lib/hecks/ports/clock.rb +5 -45
  218. data/lib/hecks/ports/extraction.rb +7 -12
  219. data/lib/hecks/ports/identity_assignment.rb +8 -29
  220. data/lib/hecks/ports/identity_generation.rb +6 -29
  221. data/lib/hecks/ports/identity_resolution.rb +2 -10
  222. data/lib/hecks/ports/key_vault.rb +9 -45
  223. data/lib/hecks/ports/persistence/append_only.rb +62 -65
  224. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  225. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  226. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  227. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  228. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
  229. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  230. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
  231. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
  232. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
  233. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
  242. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  243. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  244. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  245. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  246. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  247. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
  248. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  249. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
  250. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  251. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  252. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  253. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  254. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  255. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  256. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
  257. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
  258. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  259. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  260. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  261. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  262. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  263. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  264. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  265. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  266. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  267. data/lib/hecks/ports/persistence/state_codec.rb +23 -103
  268. data/lib/hecks/ports/persistence.rb +7 -14
  269. data/lib/hecks/ports/projection.rb +42 -84
  270. data/lib/hecks/ports/query/in_memory.rb +10 -58
  271. data/lib/hecks/ports/query/ordering.rb +11 -32
  272. data/lib/hecks/ports/query.rb +14 -37
  273. data/lib/hecks/ports.rb +2 -8
  274. data/lib/hecks/projections/bootstrap_table.rb +11 -43
  275. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  276. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  277. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  278. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  279. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  280. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  281. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  282. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  283. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  284. data/lib/hecks/projections/deploy/fargate.rb +35 -202
  285. data/lib/hecks/projections/deploy/lambda.rb +151 -679
  286. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  287. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  288. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  289. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  290. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  291. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  292. data/lib/hecks/projections/deploy/preview/template.rb +2 -58
  293. data/lib/hecks/projections/deploy/preview.rb +2 -67
  294. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  295. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  296. data/lib/hecks/projections/deploy/shared.rb +47 -146
  297. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  298. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  299. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  300. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  301. data/lib/hecks/projections/diagrams.rb +20 -582
  302. data/lib/hecks/projections/glossary/html.rb +14 -130
  303. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  304. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  305. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  306. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  307. data/lib/hecks/projections/glossary.rb +30 -222
  308. data/lib/hecks/projections/ir.rb +3 -10
  309. data/lib/hecks/projections/model/deviations.rb +15 -42
  310. data/lib/hecks/projections/model.rb +12 -51
  311. data/lib/hecks/projections/oidc.rb +12 -56
  312. data/lib/hecks/projections/parser_table.rb +9 -28
  313. data/lib/hecks/projections/reference.rb +9 -16
  314. data/lib/hecks/projections/rust_vocabulary.rb +12 -250
  315. data/lib/hecks/projections/shape.rb +3 -29
  316. data/lib/hecks/projections/statements.rb +7 -86
  317. data/lib/hecks/projections/vocabulary.rb +6 -22
  318. data/lib/hecks/projections.rb +2 -16
  319. data/lib/hecks/projector/cli_projector.rb +60 -375
  320. data/lib/hecks/projector/docs_projector.rb +10 -201
  321. data/lib/hecks/projector/exporter.rb +46 -138
  322. data/lib/hecks/projector/ir_projector.rb +2 -9
  323. data/lib/hecks/projector/narrate_projector.rb +15 -189
  324. data/lib/hecks/projector/target.rb +13 -76
  325. data/lib/hecks/projector.rb +30 -121
  326. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  327. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  328. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  329. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  330. data/lib/hecks/query_specification/common/options.rb +2 -6
  331. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  332. data/lib/hecks/query_specification/field_path.rb +37 -77
  333. data/lib/hecks/query_specification/hop_path.rb +12 -76
  334. data/lib/hecks/release/gem_pin.rb +2 -26
  335. data/lib/hecks/release/runner/ci_publisher.rb +93 -0
  336. data/lib/hecks/release/runner/commands.rb +66 -0
  337. data/lib/hecks/release/runner/console.rb +52 -0
  338. data/lib/hecks/release/runner/gem_publisher.rb +43 -0
  339. data/lib/hecks/release/runner/git.rb +48 -0
  340. data/lib/hecks/release/runner/npm_publisher.rb +75 -0
  341. data/lib/hecks/release/runner/preflight.rb +104 -0
  342. data/lib/hecks/release/runner/published.rb +55 -0
  343. data/lib/hecks/release/runner/tagger.rb +80 -0
  344. data/lib/hecks/release/runner.rb +215 -0
  345. data/lib/hecks/rendering.rb +4 -26
  346. data/lib/hecks/router/namespace_installer.rb +12 -36
  347. data/lib/hecks/router.rb +4 -8
  348. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  349. data/lib/hecks/runtime/boot_gates.rb +3 -18
  350. data/lib/hecks/runtime/caller.rb +19 -59
  351. data/lib/hecks/runtime/capability_graph.rb +5 -21
  352. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  353. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
  354. data/lib/hecks/runtime/command_interpreter.rb +125 -307
  355. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  356. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  357. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  358. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  359. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  360. data/lib/hecks/runtime/dependency_planning.rb +30 -102
  361. data/lib/hecks/runtime/dispatcher.rb +82 -241
  362. data/lib/hecks/runtime/entity_element.rb +40 -462
  363. data/lib/hecks/runtime/entity_interpreter.rb +65 -220
  364. data/lib/hecks/runtime/errors.rb +32 -115
  365. data/lib/hecks/runtime/event.rb +3 -25
  366. data/lib/hecks/runtime/identity.rb +18 -154
  367. data/lib/hecks/runtime/instance.rb +18 -150
  368. data/lib/hecks/runtime/interpreting.rb +11 -70
  369. data/lib/hecks/runtime/invocation.rb +28 -164
  370. data/lib/hecks/runtime/loader.rb +48 -186
  371. data/lib/hecks/runtime/outbox.rb +38 -261
  372. data/lib/hecks/runtime/policy_interpreter.rb +38 -200
  373. data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
  374. data/lib/hecks/runtime/query_interpreter.rb +45 -187
  375. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  376. data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
  377. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  378. data/lib/hecks/runtime/reference_hop.rb +8 -81
  379. data/lib/hecks/runtime/refusal_wording.rb +8 -89
  380. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  381. data/lib/hecks/runtime/registry/verification.rb +52 -225
  382. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  383. data/lib/hecks/runtime/registry.rb +103 -244
  384. data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
  385. data/lib/hecks/runtime/routing.rb +4 -15
  386. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  387. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  388. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  389. data/lib/hecks/runtime/tenant_check.rb +6 -68
  390. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  391. data/lib/hecks/runtime/value/admission.rb +16 -67
  392. data/lib/hecks/runtime/value/coercion.rb +155 -641
  393. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  394. data/lib/hecks/runtime/value.rb +12 -84
  395. data/lib/hecks/runtime.rb +17 -65
  396. data/lib/hecks/storehouse.rb +146 -567
  397. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
  398. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  399. data/lib/hecks/vendoring/git_environment.rb +2 -8
  400. data/lib/hecks/vendoring/git_source.rb +4 -10
  401. data/lib/hecks/vendoring.rb +7 -46
  402. data/lib/hecks/version.rb +3 -14
  403. data/lib/hecks/vocabulary.rb +5 -0
  404. data/lib/hecks.rb +32 -82
  405. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  406. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  407. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  408. metadata +30 -59
  409. data/lib/hecks/bench/cli.rb +0 -74
  410. data/lib/hecks/bench/environment.rb +0 -100
  411. data/lib/hecks/bench/postgres_probe.rb +0 -41
  412. data/lib/hecks/bench/report.rb +0 -116
  413. data/lib/hecks/bench/ruby_runner.rb +0 -151
  414. data/lib/hecks/bench/run.rb +0 -55
  415. data/lib/hecks/bench/rust_runner.rb +0 -165
  416. data/lib/hecks/bench/stats.rb +0 -75
  417. data/lib/hecks/bench/suite.rb +0 -172
  418. data/lib/hecks/bench/workload.rb +0 -137
  419. data/lib/hecks/bench.rb +0 -28
  420. data/lib/hecks/codemod.rb +0 -443
  421. data/lib/hecks/corpus.rb +0 -479
  422. data/lib/hecks/doc/reference.rb +0 -585
  423. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
  424. data/lib/hecks/fuzzing/combination_miner.rb +0 -178
  425. data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
  426. data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
  427. data/lib/hecks/fuzzing/differential.rb +0 -192
  428. data/lib/hecks/fuzzing/domain_generator.rb +0 -871
  429. data/lib/hecks/fuzzing/era_boundary.rb +0 -154
  430. data/lib/hecks/fuzzing/form_census.rb +0 -285
  431. data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
  432. data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
  433. data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
  434. data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
  435. data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
  436. data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
  437. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
  438. data/lib/hecks/fuzzing/properties/guards.rb +0 -398
  439. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
  440. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
  441. data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
  442. data/lib/hecks/fuzzing/properties/querying.rb +0 -260
  443. data/lib/hecks/fuzzing/properties.rb +0 -267
  444. data/lib/hecks/fuzzing/qa_settings.rb +0 -164
  445. data/lib/hecks/fuzzing/replay.rb +0 -930
  446. data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
  447. data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
  448. data/lib/hecks/fuzzing/self_consistency.rb +0 -825
  449. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
  450. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
  451. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
  452. data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
  453. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
  454. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
  455. data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
  456. data/lib/hecks/fuzzing/shrinker.rb +0 -309
  457. data/lib/hecks/fuzzing/structural_skips.rb +0 -53
  458. data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
  459. data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
  460. data/lib/hecks/fuzzing/value_generator.rb +0 -340
  461. data/lib/hecks/fuzzing.rb +0 -23
  462. data/lib/hecks/grammar/evolve.rb +0 -524
  463. data/lib/hecks/query_ir.rb +0 -482
@@ -1,20 +1,13 @@
1
1
  Hecks.bluebook "Identity" do
2
2
  vision "Authentication proves an identifier; the organization decides what that identity means."
3
- # S13, ADR 0025 (coverage standard) — GENERIC, not `supporting`: an
4
- # OIDC-shaped external identifier is the textbook generic subdomain
5
- # (Vernon's own example of one), off-the-shelf and buyable —
6
- # `Governance` (role/scope RBAC beside it) stays `supporting`
7
- # instead, since ITS OWN model is bespoke to this codebase's actor/
8
- # role/scope shape, not a drop-in replaceable concept the way an
9
- # identity provider is.
3
+ # Generic, not `supporting`: an OIDC-shaped external identifier is the textbook generic
4
+ # subdomain. Governance's role/scope RBAC is bespoke to this codebase, so it stays
5
+ # `supporting` (ADR 0025).
10
6
  generic
11
7
 
12
- # WHAT THIS CHAPTER ANSWERS FOR EVERY DOMAIN THAT ATTACHES IT. Same
13
- # declared-not-named shape Governance's own `provides "authorization"`
14
- # already is. rust/host does not build this chapter's payloads — any
15
- # field mapping lives on the consuming hecksagon's `translates` ACL
16
- # (any field; this chapter does not list which). Link's reference is
17
- # `identity`, not `identity_id` and not `to:`.
8
+ # What this chapter answers for every attaching domain, declared rather than named as
9
+ # Governance's `provides "authorization"` is. Field mapping lives on the consuming
10
+ # hecksagon's `translates` ACL; Link's reference is `identity`, not `identity_id` or `to:`.
18
11
  provides "identity",
19
12
  register: "Identity.Register",
20
13
  link: "ExternalIdentifier.Link",
@@ -32,10 +25,8 @@ Hecks.bluebook "Identity" do
32
25
  invariant("an identity id is present") { !value.to_s.empty? }
33
26
  end
34
27
 
35
- # No natural key exists for "a newly recognized identity" — the
36
- # caller mints identity_id via Ports::IdentityGeneration.uuid
37
- # before dispatching (see spec/ports/identity_generation_spec.rb),
38
- # the same pattern proven there against Pizzas.
28
+ # No natural key exists for a new identity: the caller mints `identity_id` via
29
+ # `Ports::IdentityGeneration.uuid` before dispatching.
39
30
  command "Register" do
40
31
  role "Identity registrar"
41
32
  goal "Recognize an identity"
@@ -70,9 +61,7 @@ Hecks.bluebook "Identity" do
70
61
  invariant("a subject is present") { !value.to_s.empty? }
71
62
  end
72
63
 
73
- # `key` is deliberately not derived here — a caller-side concern
74
- # (e.g. SHA256 of issuer+subject), same as any other identity
75
- # field this domain never mints itself.
64
+ # `key` is not derived here; the caller derives it (e.g. SHA256 of issuer+subject).
76
65
  command "Link" do
77
66
  role "Identity registrar"
78
67
  goal "Associate an external authenticated subject with an identity"
@@ -85,12 +74,8 @@ Hecks.bluebook "Identity" do
85
74
  emits ExternalIdentifierLinked
86
75
  end
87
76
 
88
- # THE OIDC-SHAPED LOOKUP — a token hands over `(issuer, subject)`,
89
- # never the `key` this aggregate is actually identified by (`key`
90
- # is a caller-side derivation, deliberately not reproduced here —
91
- # see `Link`'s own comment). `identity` rides the row already,
92
- # from `reference_to Identity` above, so a caller reads it straight
93
- # off the match rather than needing a second query.
77
+ # The OIDC-shaped lookup: a token hands over `(issuer, subject)`, never `key`. `identity`
78
+ # rides the row from `reference_to Identity`, so no second query is needed.
94
79
  query "ResolvedBy" do
95
80
  description "The external identifier linked to this exact (issuer, subject) pair, if any."
96
81
  attribute :issuer, Issuer
@@ -2,12 +2,7 @@ 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
- # A DOMAIN ATTACHING THIS NEVER MARKS ITSELF — `Mark`'s `role
6
- # "Deployment"` matches every other wiring-time command in this
7
- # codebase (`Hecksagon::UsesFramework`, `Tenancy::Tenant.Register`):
8
- # something outside the domain's own bluebook decides a field is
9
- # sensitive, the same way persistence binds are a wiring decision
10
- # and not baked into an aggregate's own declaration.
5
+ # A domain never marks itself: `Mark` is a wiring-time command (role "Deployment").
11
6
  aggregate "Marking" do
12
7
  description "One attribute of one domain's own aggregate, flagged sensitive — and the role required to read it unredacted."
13
8
 
@@ -23,20 +18,13 @@ Hecks.bluebook "Privacy" do
23
18
  invariant("a marking names the domain it applies to") { !value.to_s.empty? }
24
19
  end
25
20
 
26
- # DOTTED, same convention Forms' own `Field#path` and a query's
27
- # cross-object `where` clause already use — `"attendee.medications"`,
28
- # not a bare leaf name, so a marking can reach into a nested value
29
- # object rather than only a top-level attribute.
21
+ # Dotted, e.g. "attendee.medications", so a marking can reach a nested value object.
30
22
  value_object "AttributePath" do
31
23
  attribute :value, String
32
24
  invariant("a marking names an attribute path") { !value.to_s.empty? }
33
25
  end
34
26
 
35
- # OPEN-ENDED ON PURPOSE — "pii", "phi", whatever else a consuming
36
- # domain finds itself needing, none of it enumerated here. This
37
- # bluebook is the mechanism (mark, gate, redact); it does not also
38
- # own the vocabulary of sensitivity categories that exist in the
39
- # world.
27
+ # Open-ended on purpose ("pii", "phi", ...): this bluebook does not own the vocabulary.
40
28
  value_object "Category" do
41
29
  attribute :value, String
42
30
  invariant("a marking is categorized") { !value.to_s.empty? }
@@ -75,15 +63,8 @@ Hecks.bluebook "Privacy" do
75
63
  end
76
64
  end
77
65
 
78
- # **Cryptoshredding** — a right-to-erasure request satisfied without
79
- # rewriting or deleting a single event. `key_reference` is an opaque
80
- # handle a caller obtains from `Ports::KeyVault.issue` before
81
- # dispatching `Issue`, the same "nothing is minted inside a bluebook"
82
- # convention `Identity::Register`'s own `identity_id` and
83
- # `Delivery::Record`'s own `message_id` already hold to (the
84
- # expression sublanguage cannot call a port at all). The key material
85
- # itself never appears here or on any emitted event — only the fact
86
- # that a reference exists, and the fact that it was destroyed.
66
+ # Cryptoshredding: erasure without rewriting events. `key_reference` is an opaque handle
67
+ # from `Ports::KeyVault.issue`, obtained before `Issue`; key material never appears here.
87
68
  aggregate "SubjectKey" do
88
69
  description "One data subject's own encryption key, from the moment it exists to the moment it is destroyed."
89
70
 
@@ -108,9 +89,7 @@ Hecks.bluebook "Privacy" do
108
89
  invariant("a key carries the vault's own opaque reference to it") { !value.to_s.empty? }
109
90
  end
110
91
 
111
- # `Shred`'s own guard against running twice — the same mechanism
112
- # `Compliance::PrivacyReview`'s `Clear`/`Escalate` already use rather
113
- # than an optional timestamp plus a hand-written `given`.
92
+ # Guards `Shred` against running twice.
114
93
  lifecycle :status, default: "active" do
115
94
  transition "Shred" => "shredded", from: "active"
116
95
  end
@@ -130,12 +109,8 @@ Hecks.bluebook "Privacy" do
130
109
  emits SubjectKeyIssued
131
110
  end
132
111
 
133
- # **Records destruction, never performs it** — the actual
134
- # `Ports::KeyVault.destroy` call happens in driving-side code before
135
- # this is ever dispatched, the same boundary `send_issue.rb` draws
136
- # around `Delivery::Record` for an already-sent email. This
137
- # command's own job is to make an already-irreversible fact
138
- # durable, not to cause it.
112
+ # Records the destruction, never performs it: `Ports::KeyVault.destroy` runs in
113
+ # driving-side code before this is dispatched.
139
114
  command "Shred" do
140
115
  role "Privacy officer"
141
116
  goal "Mark this subject's key destroyed, so its ciphertext is recorded as permanently unrecoverable"
@@ -1,67 +1,12 @@
1
1
  require_relative "runtime/registry"
2
2
 
3
3
  module Hecks
4
- # **The registry of framework bluebooks** — Governance, Identity, and
5
- # whatever lands beside them in `lib/hecks/framework/bluebook/`:
6
- # domain-agnostic chapters no single example owns, shared by reference
7
- # rather than copied into every domain that wants one.
8
- #
9
- # ## Where it lives
10
- #
11
- # Under `lib/`, not a top-level sibling — a real consumer (embryonaut)
12
- # vendors only `lib/` (`bin/vendor-hecks`, and this gem's own
13
- # `hecks.gemspec`, both glob `lib/**/*`), so a `framework/`
14
- # sitting beside `lib/` rather than inside it packaged and vendored
15
- # cleanly but left `uses_framework` finding nothing at runtime —
16
- # `Framework::ROOT` pointed at a directory that simply never shipped.
17
- # Nothing in this repo's own suite caught it, since every spec here
18
- # reads the working tree directly; only vendoring into a real consumer
19
- # did. Same reasoning `lib/hecks/language/bluebook/` already
20
- # settled for the self-hosted grammar's own `.bluebook` files —
21
- # non-Ruby data a module owns lives inside `lib/` with the code that
22
- # reads it, not beside it.
23
- #
24
- # ## Derived, not hand-listed
25
- #
26
- # Derived from the directory, not hand-listed a second time — the same
27
- # reasoning `Assembly::CONTRACTS` gives for reading the language's own
28
- # fields from a table instead of restating them: a member added here
29
- # and forgotten in a list would be a member `uses_framework` could
30
- # never find, and a hand-kept list is exactly the shape that goes
31
- # stale in silence. `spec/corpus_spec.rb`'s own `FRAMEWORK_MEMBERS`
32
- # glob is the precedent this mirrors.
33
- #
34
- # ## Naming
35
- #
36
- # Named by file stem, capitalized — `governance.bluebook` holds
37
- # `Hecks.bluebook "Governance"`, the same one-to-one spelling every
38
- # other chapter in this codebase already keeps between its filename
39
- # and its declared name.
4
+ # Registry of framework bluebooks (Governance, Identity, ...) in `lib/hecks/framework/bluebook/`.
5
+ # Members are derived from the directory and named by capitalized file stem.
40
6
  module Framework
41
- # Loaded from its own real path, always — never a copy. A domain
42
- # booted through `Fuzzing::IsolatedBoot`'s tmp-directory copy still
43
- # reaches the same `framework/bluebook/governance.bluebook` this
44
- # constant points at, because `uses_framework` runs `Kernel.load`
45
- # against `ROOT`, not against anything inside the copied domain
46
- # directory — there is nothing here for a relocated copy to break,
47
- # the way a symlink carried along with the copy would.
48
- #
49
- # Only the bluebook — a framework member's own `.hecksagon`, if it
50
- # has one, is not auto-loaded. Persistence is a wiring decision, the
51
- # same as any other aggregate's, and belongs to whoever is doing the
52
- # deploying, not to a default baked into the framework member
53
- # itself: a consuming app needs `Governance::RoleAssignment` durable
54
- # (Postgres, say), and a framework member hard-coding Memory for its
55
- # own specs would silently make that decision for every app that
56
- # attaches it. The consuming app declares its own, separate
57
- # `Hecks.hecksagon "Governance" do ... end` block for that — not
58
- # binds folded into its own hecksagon, which would build but never
59
- # resolve: `Ports::Persistence::BindingPolicy.resolve` looks up
60
- # `registry.hecksagon` by the aggregate's own domain name, not the
61
- # domain doing the binding, the one invariant this runtime holds
62
- # everywhere else too. See `examples/banking/bluebook/banking.hecksagon`
63
- # for the pattern — a real `.hecksagon` file can hold more than one
64
- # `Hecks.hecksagon` call, one per domain it wires.
7
+ # Directory the members load from, never a copy, so relocated domain copies still resolve.
8
+ # Lives under `lib/` because consumers vendor only `lib/`.
9
+ # Only the bluebook loads: persistence is the consumer's own `Hecks.hecksagon` block.
65
10
  ROOT = File.expand_path("framework/bluebook", __dir__).freeze
66
11
 
67
12
  # Every framework member available to attach, by declared name.
@@ -74,11 +19,7 @@ module Hecks
74
19
  end
75
20
  end
76
21
 
77
- # Every member whose own bluebook declares `provides capability` —
78
- # read off the member's real IR (each loaded into a scratch registry,
79
- # never the caller's), not off its name. Used where a check needs to
80
- # say which member would satisfy it (`refuse_ungoverned_roles!`'s own
81
- # suggestion, `Fuzzing::TargetCapabilities`).
22
+ # Every member whose bluebook declares `provides capability`, read from its IR, not its name.
82
23
  #
83
24
  # @param capability [String, Symbol] the capability name to look for
84
25
  # @return [Array<String>] the names of every framework member that provides it,
@@ -101,9 +42,7 @@ module Hecks
101
42
  lib = File.expand_path("..", __dir__)
102
43
  registry = Runtime::Registry.new
103
44
  Hecks.with_registry(registry) do
104
- # The same four a chapter needs to build at all (a predicate's
105
- # source is recovered through the extraction port) — the seed
106
- # `Grammar#grammar_chapters` and `bin/model_check` use.
45
+ # A chapter needs these four to build (predicate source is recovered via extraction).
107
46
  Kernel.load(File.join(lib, "hecks/ports/persistence.port"))
108
47
  Kernel.load(File.join(lib, "hecks/ports/extraction.port"))
109
48
  Kernel.load(File.join(lib, "hecks/adapters/driven/memory.adapter"))
@@ -113,18 +52,10 @@ module Hecks
113
52
  registry.bluebook(name.to_s)
114
53
  end
115
54
 
116
- # Idempotent, per registry — `uses_framework` is now called more than
117
- # once for the same member within a single boot (S8: a domain
118
- # attaching Governance for its own role check, plus a framework
119
- # sibling attaching it too, e.g. `banking.hecksagon`'s Identity
120
- # block). `Kernel.load` always re-executes the file, unlike
121
- # `require`, so a second call would re-run `Hecks.bluebook
122
- # "Governance"` a second time — and the self-hosting meta-domain
123
- # records every declaration as a real dispatched command against its
124
- # own ledger, so a second `Declare` for the same aggregate is a real
125
- # `AlreadyExists`, not a no-op. Skipped once the member's bluebook is
126
- # already registered in this registry — the same chapter, not merely
127
- # a same-named one from a stale prior boot.
55
+ # Loads a member's bluebook unless this registry already holds it.
56
+ #
57
+ # `Kernel.load` re-executes the file, and a second `Declare` of the same aggregate is
58
+ # `AlreadyExists`, so repeated `uses_framework` calls in one boot must skip.
128
59
  #
129
60
  # @param name [String, Symbol] the member's name, such as `"Governance"`
130
61
  # @return [Boolean, nil] true when this call loaded the member's bluebook, nil when
data/lib/hecks/freezer.rb CHANGED
@@ -1,38 +1,10 @@
1
1
  module Hecks
2
- # The one place that knows how to freeze a domain value.
3
- #
4
- # Freezing here has been fixed four times in four places, each time by
5
- # topping the container and leaving the contents: list attributes, the
6
- # event log, query rows, and value objects. `.freeze` on a Hash stops a
7
- # key being added or removed and nothing else — the String, Array or
8
- # Hash a field holds stays mutable, so a caller reaches straight
9
- # through and edits in place. Each fix looked complete and none was.
10
- #
11
- # ## What should be frozen, and why it is not everything
12
- #
13
- # a value object has no identity to change over. `with` already
14
- # answers a new one rather than mutating, so freezing it through is
15
- # what it always claimed to be.
16
- #
17
- # an emitted event is a record of something that happened. A mutable
18
- # audit trail is not one.
19
- #
20
- # a query row is an answer, not a handle — mutating one edits nobody's
21
- # state and silently disagrees with the store.
22
- #
23
- # an instance's state is not frozen, deliberately: the interpreter
24
- # builds it up across a dispatch, and a command's whole job is to
25
- # change it. Its values are frozen; the holder is not.
26
- #
27
- # a command's arguments are not frozen either. They arrive from
28
- # outside, are normalised and coerced on the way in, and the coerced
29
- # result is what becomes a frozen value.
2
+ # The one place that freezes a domain value all the way down, not just its container.
3
+ # Instance state and command arguments are deliberately left unfrozen; values and events are.
30
4
  module Freezer
31
5
  module_function
32
6
 
33
- # Numbers, symbols, nil and booleans are already immediate or frozen;
34
- # a Value froze itself when it was built. What is left is the mutable
35
- # trio, and each has to be walked rather than topped.
7
+ # Freezes a Hash, Array or String and everything inside it.
36
8
  #
37
9
  # @param held [Object] any domain value
38
10
  # @return [Object] `held`, recursively frozen if it is a Hash, Array, or
@@ -46,17 +18,13 @@ module Hecks
46
18
  end
47
19
  end
48
20
 
49
- # The question a gate asks, rather than the act. Answers false for the
50
- # first thing that is reachable and mutable, which is what makes a
51
- # failure message worth reading.
21
+ # True when `held` and everything reachable from it is frozen.
52
22
  #
53
23
  # @param held [Object] any domain value
54
24
  # @return [Boolean] true if `held` and everything reachable from it is frozen
55
25
  def deeply_frozen?(held) = unfrozen_within(held).nil?
56
26
 
57
27
  # The path to the first mutable thing reachable from `held`, or nil.
58
- # A path rather than a boolean because "something in this event is
59
- # mutable" is not an actionable sentence.
60
28
  #
61
29
  # @param held [Object] any domain value
62
30
  # @param path [Array<String>] the owner path accumulated by the recursive
@@ -72,9 +40,7 @@ module Hecks
72
40
  end
73
41
  end
74
42
 
75
- # Immediates are frozen in every Ruby that matters, but asking
76
- # `frozen?` of them and trusting the answer has bitten enough people
77
- # that it is worth being explicit.
43
+ # Explicit rather than trusting `frozen?` on immediates.
78
44
  #
79
45
  # @param held [Object] any domain value
80
46
  # @return [Boolean] true if `held` is nil, true, false, a Numeric, or a Symbol
@@ -6,21 +6,9 @@ Hecks.bluebook "Expression" do
6
6
  aggregate "Operator" do
7
7
  description "One admitted operation — its symbol, its precedence, and how it reads in every target that must evaluate it."
8
8
 
9
- # WHAT IS NOT HERE, on purpose. The outer grammar
10
- # has two rules that are not operators: parenthesization (a structural
11
- # strip-and-recurse, no symbol of its own) and the bare-leaf fallback
12
- # (whatever matches nothing else falls through to the inner grammar).
13
- # Its inner grammar has three more: integer/float/string/bool/nil/
14
- # array literals and the dotted-lookup fallback are TERMINAL
15
- # productions — they recognize text, they do not combine operands,
16
- # and they have nothing meaningful to render per target (a literal's
17
- # spelling does not differ between targets the way an operation's
18
- # might — `rust/src/kernel/expr.rs`'s own `Expr::Array` is a LEAF
19
- # there too, for the identical reason, not routed through
20
- # `OperatorCategory`).
21
- # Forcing them into this shape would stretch `renderings` and the
22
- # Arity invariant past what they mean. They stay declared only in
23
- # prose — named here rather than silently left out.
9
+ # Not operators, so not declared here: parenthesization, the bare-leaf fallback,
10
+ # and the terminal literals and dotted lookup. They recognize text rather than
11
+ # combine operands, and a literal reads the same in every target.
24
12
  identified_by :symbol
25
13
 
26
14
  attribute :symbol, OperatorSymbol
@@ -54,47 +42,34 @@ Hecks.bluebook "Expression" do
54
42
 
55
43
  value_object "Arity" do
56
44
  attribute :value, Integer
57
- # WRITTEN ACROSS LINES ON PURPOSE, and this is the only predicate in the
58
- # corpus that is. A CONTINUATION line is where extraction used to break:
59
- # a naive line join reads `value > 0 && && value <= 3` — a different
60
- # canonical form for the same source, waiting for the first multi-line
61
- # rule anyone wrote. Every predicate here was kept on one line to dodge
62
- # that. The join is continuation-aware now, so this case holds the fix:
63
- # if it regresses, the canonical text of THIS invariant changes and the
64
- # golden IR goes red.
45
+ # Written across lines on purpose: it pins continuation-aware line joining in
46
+ # extraction. If that regresses, this invariant's canonical text changes and
47
+ # the golden IR goes red.
65
48
  invariant("an operator takes one, two or three operands") do
66
49
  value > 0 &&
67
50
  value <= 3
68
51
  end
69
52
  end
70
53
 
71
- # OUTER checks a leaf against `.include?`/comparators/`!` before falling
72
- # through to INNER's arithmetic/dotted-lookup grammar — two stacked
73
- # grammars. Which one an operator belongs
74
- # to is not derivable from its symbol alone (`+` reads like it could be
75
- # either), so it is its own column rather than inferred.
54
+ # The outer grammar checks `.include?`, comparators and `!` before falling through
55
+ # to the inner arithmetic and dotted-lookup grammar. The symbol alone does not say
56
+ # which one an operator belongs to, so it is its own column.
76
57
  value_object "Grammar" do
77
58
  attribute :value, String
78
59
  invariant("an operator belongs to one of the two stacked grammars") { !value.to_s.empty? }
79
60
  end
80
61
 
81
- # HOW the check recognizes this operator's text, not WHERE it binds
82
- # (that's precedence) or WHEN it's tried (that's position). Four shapes
83
- # cover every admitted operator: split at a top-level occurrence
84
- # (`||`, comparators), strip a leading marker (`!`), strip a trailing
85
- # suffix (`.empty?`), or match a call-with-argument pattern
86
- # (`.include?(needle)`).
62
+ # How the check recognizes an operator's text: split at a top-level occurrence
63
+ # (`||`), strip a leading marker (`!`) or trailing suffix (`.empty?`), or match a
64
+ # call pattern (`.include?(needle)`).
87
65
  value_object "Strategy" do
88
66
  attribute :value, String
89
67
  invariant("an operator names how its check recognizes it") { !value.to_s.empty? }
90
68
  end
91
69
 
92
- # THE WITHIN-GRAMMAR CHECK ORDER — what precedence alone cannot say,
93
- # since the six comparators all share one precedence tier and something
94
- # still has to break the tie (grammar.md: `>=` before `<=` before `<`
95
- # before `>` before `==` before `!=`, so `<` splitting does not fire
96
- # inside `>=`). Scoped per `grammar`, mirroring Normalisation's own
97
- # Position column below — each grammar starts its own count at 1.
70
+ # The check order within a grammar, counted from 1 per grammar. It breaks the tie
71
+ # precedence cannot: the six comparators share a tier, and `>=` must be tried
72
+ # before `>` so a split on `>` does not fire inside `>=`.
98
73
  value_object "Position" do
99
74
  attribute :value, Integer
100
75
  invariant("an operator sits somewhere in its grammar's check order") { value > 0 }
@@ -18,12 +18,9 @@ Hecks.bluebook "Translation" do
18
18
  transition "Retire" => "retired", from: "admitted"
19
19
  end
20
20
 
21
- # THE CLOSED SET OF RULE KINDS — declared as members, not a hand-rolled
22
- # OR-chain, so the set is data a conformance spec can hold the live
23
- # builder to (spec/translation_vocabulary_conformance_spec.rb). Nine of
24
- # these are TranslationAggregateBuilder's own rule methods ; "retired" is
25
- # the edge-level declaration (TranslationBuilder#retired), in the set
26
- # because it is one admitted way a shape survives — by not surviving.
21
+ # The closed set of rule kinds, kept as data so a conformance spec can hold the
22
+ # builder to it. All but "retired" are TranslationAggregateBuilder rule methods;
23
+ # "retired" is the edge-level declaration (TranslationBuilder#retired).
27
24
  value_object "Kind" do
28
25
  attribute :value, String,
29
26
  one_of: ["rename", "move", "convert", "drop", "retype", "retired", "compute", "rekey",
data/lib/hecks/grammar.rb CHANGED
@@ -1,32 +1,23 @@
1
1
  require "json"
2
2
 
3
- # The whole framework, deliberately: booting a grammar chapter exercises
4
- # the DSL, the meta-validator, and the runtime — and nothing the entry
5
- # point loads ever requires this file back, so the require is acyclic.
3
+ # Loads the whole framework on purpose; nothing the entry point loads
4
+ # requires this file back, so the require is acyclic.
6
5
  require_relative "../hecks"
7
6
 
8
7
  module Hecks
9
- # The sublanguage grammar domains (grammar/*.bluebook) and the one boot
10
- # path for reading them as data — the expression chapter replayed
11
- # through its own admission ledger, so anything derived from it (the
12
- # operator projections, the conformance specs) reads the set that
13
- # actually survived the Admit gates, never a hand-copied list.
8
+ # The sublanguage grammar domains (grammar/*.bluebook) and the one boot path
9
+ # for reading them as data, replayed through the expression admission ledger.
14
10
  #
15
- # Booted on call, never at require: the Prism adapter normalises every
16
- # predicate through CanonicalForm while a bluebook loads, so the
17
- # expression machinery cannot boot the chapter that configures it —
18
- # this module exists precisely so generators and specs boot it in a
19
- # scratch registry instead.
11
+ # Booted on call, never at require: the Prism adapter normalises predicates
12
+ # while a bluebook loads, so the expression machinery cannot boot its own chapter.
20
13
  module Grammar
21
14
  DIR = File.expand_path("grammar", __dir__)
22
15
  LEDGER = File.join(DIR, "expression_operators.json")
23
16
 
24
17
  module_function
25
18
 
26
- # Boot the expression chapter and replay the admission ledger through
27
- # its real commands. A refused step raises — a generator running off
28
- # a half-admitted ledger would project a table the gates never
29
- # accepted.
19
+ # Boots the expression chapter and replays the admission ledger through
20
+ # its real commands; a refused step raises.
30
21
  #
31
22
  # @return [Runtime::Dispatcher] the dispatcher bound to the booted, replayed
32
23
  # expression chapter
@@ -104,16 +95,9 @@ module Hecks
104
95
  registry.repository("Expression", aggregate).all
105
96
  end
106
97
 
107
- # The operators the language stands on. Every guard and invariant in
108
- # the language's own chapters — the meta-domain (Bluebook, World) and
109
- # the grammar chapters beside this file — evaluates through the very
110
- # operator table the ledger admits. An operator one of those
111
- # predicates uses is self-bearing: retire it and the language can no
112
- # longer read its own rules — found the hard way, as a projection
113
- # missing `!=` that could not boot the chapter to fix itself. This
114
- # derives the set, with a usage site per operator, so the generator
115
- # and the conformance spec can refuse the retirement by name instead
116
- # of wedging.
98
+ # The operators the language's own guards and invariants (Bluebook, World and
99
+ # the grammar chapters) evaluate through. Retiring one would leave the
100
+ # language unable to read its own rules, so callers refuse it by name.
117
101
  #
118
102
  # @return [Hash{String => Array<String>}] each self-bearing operator symbol
119
103
  # mapped to the `"Chapter Aggregate.command"`/`"Chapter Aggregate::ValueObject"`
@@ -147,8 +131,7 @@ module Hecks
147
131
  sites.transform_values(&:uniq)
148
132
  end
149
133
 
150
- # Every grammar/*.bluebook chapter, booted the same way the corpus
151
- # boots them — each alone, in a scratch registry.
134
+ # Every grammar/*.bluebook chapter, each booted alone in a scratch registry.
152
135
  #
153
136
  # @return [Array<Class>] each grammar chapter, booted alone in its own scratch
154
137
  # registry
@@ -167,9 +150,8 @@ module Hecks
167
150
  end
168
151
  end
169
152
 
170
- # Which admitted operators one canonical text evaluates through —
171
- # the evaluator's own parse, walked for its operator nodes, leaves
172
- # walked for the resolver's arithmetic.
153
+ # Which admitted operators one canonical text evaluates through, found by
154
+ # walking the evaluator's own parse.
173
155
  #
174
156
  # @param canonical [String] canonical expression text to parse
175
157
  # @return [Array<String>] operator symbols the expression evaluates through, or
@@ -184,15 +166,8 @@ module Hecks
184
166
  walk_operators(node, evaluator).uniq
185
167
  end
186
168
 
187
- # A recursive descent over a closed, declared set of AST node types
188
- # (Evaluator's boolean/compare/include nodes, Resolver's arithmetic
189
- # nodes, and the generic Struct fallback) — each branch does the
190
- # same one thing (name the node's own operator, recurse into its
191
- # children) and the branches don't interact, but the ABC score adds
192
- # every branch's cost together. Splitting the case out per node type
193
- # would trade one place that shows the whole operator vocabulary for
194
- # several that each show a fragment, with no reduction in real
195
- # complexity.
169
+ # One case over the closed set of AST node types, kept together so the whole
170
+ # operator vocabulary reads in one place.
196
171
  # @param node [Object] an evaluator/resolver AST node, or a Struct fallback
197
172
  # @param evaluator [Module] `Bluebook::Expression::Evaluator`, passed through
198
173
  # so nested calls don't re-resolve the constant