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,85 +1,20 @@
1
1
  require "digest"
2
2
  require "fileutils"
3
+ require_relative "../../cache_dir"
3
4
 
4
5
  module Hecks
5
6
  module Bluebook
6
7
  module MetaValidator
7
- # S14, ADR 0026 — dispatches the language's own grammar table into
8
- # itself, once, so `Keyword`/`Argument`'s own `status` genuinely is a
9
- # lifecycle — checked at real dispatch time (the same admission/
10
- # coercion/lifecycle-guard door every other command goes through),
11
- # not merely declared and never exercised.
8
+ # Dispatches the language's own grammar table through a real runtime so
9
+ # `Keyword`/`Argument` status is a lifecycle, not just declared (ADR 0026).
12
10
  #
13
- # ## The source stays static
14
- #
15
- # Aggregate-local `KeywordSeed`/`ArgumentSeed` value objects (still
16
- # hand-written `member` rows — now beside the concepts they spell)
17
- # are what gets written ; this is what turns them into what gets
18
- # read. `Judge`/`Reconstruction` already draw exactly this line
19
- # everywhere else in the meta-domain (a chapter's own declarations
20
- # versus what gets dispatched from them) — this runs the same
21
- # distinction one level further out, for the language's own grammar
22
- # table.
23
- #
24
- # ## A dedicated runtime
25
- #
26
- # Not `MetaValidator.fresh_runtime`. That one is reserved for
27
- # `Judge`'s own bootstrap (dispatching a chapter's declarations into
28
- # the meta-domain's grammar) — a different act from this one
29
- # (dispatching the meta-domain's own grammar table data into a live
30
- # "Bluebook" domain instance). Sharing the runtime would let one
31
- # boot's own repository state leak into the other's.
32
- #
33
- # ## Usage
34
- #
35
- # MetaValidator.syntax_table # => { keywords: [...], arguments: [...] }
36
- #
37
- # each row a plain Hash, string values, `status` included — the
38
- # exact shape `ParserTable`/`syntax_conformance_spec` already read
39
- # off the old closed-set members, so neither consumer had to change
40
- # what it does with a row, only where the row comes from.
11
+ # SyntaxBoot.call # => { keywords: [...], arguments: [...] }
41
12
  module SyntaxBoot
42
13
  module_function
43
14
 
44
- # Memoized the same way `MetaValidator.grammar_registry` itself
45
- # is — the ~284-command dispatch sequence below is real work, not
46
- # something three separate callers (ParserTable, syntax_
47
- # conformance_spec, bin/reference) should each pay for on every
48
- # call.
49
- #
50
- # Keyed by the grammar registry's own chapter set, not by a
51
- # "ready" flag. `boot` reads exactly two things: the registry's
52
- # "Bluebook" chapter (the core seed rows) and every chapter in the
53
- # registry that `attaches_to` a core context (Paging's rows). So
54
- # the table is a pure function of which chapter objects the
55
- # registry holds — and that is the cache key: the same chapters,
56
- # by identity, mean the same table; a chapter replaced (the
57
- # fixpoint judge swapping a raw chapter for its assembled self)
58
- # or added (`load_attached_grammar_into`) means a fresh boot.
59
- #
60
- # Why not the earlier `grammar_registry_ready?` guard. That guard
61
- # was right about the hazard — a snapshot taken mid-build, before
62
- # Paging attached, would be missing limit/offset/cursor/nulls
63
- # forever — and wrong about the cost of its cure. It refused to
64
- # cache anything until the whole grammar registry had finished
65
- # building, calling that window "narrow" and recomputing in it
66
- # "cheap". Measured (hecks_ai_training, a six-entity chess domain,
67
- # 2026-08-22): every `word_gate_dispatch` landing in that window
68
- # re-ran the full ~284-dispatch boot at ~0.76s each — 42 times per
69
- # process, 32 of a 35-second `Hecks.boot`, 95% of which had
70
- # nothing to do with the domain being booted. Keying on the
71
- # chapter set closes the same hazard by construction (a snapshot
72
- # can only be served while the chapters it was read from are
73
- # still the chapters the registry holds) and lets the window's
74
- # own repeated, identical calls share one boot. A registry reset
75
- # (fixpoint_spec's own `@grammar_registry = nil`) yields new
76
- # chapter objects, so it invalidates this the same way it always
77
- # invalidated `grammar_registry_ready?`.
15
+ # Memoized per grammar-registry chapter set (identity, not a "ready"
16
+ # flag), and cross-process on disk, since a full boot is real work.
78
17
  #
79
- # `equal?`, not `==`, on the chapters — identity is the fact being
80
- # tracked. Holding the chapter objects themselves (not their ids)
81
- # in the key also means a collected chapter can never hand its id
82
- # to a newcomer behind this cache's back.
83
18
  # @return [Hash{Symbol => Array<Hash{Symbol => String}>}] `:keywords`
84
19
  # and `:arguments`, each an array of plain, string-valued row
85
20
  # hashes (`status` included)
@@ -98,15 +33,8 @@ module Hecks
98
33
  result
99
34
  end
100
35
 
101
- # Compares the in-process cache key against the registry's current
102
- # chapters.
103
- #
104
- # @param cached [Array<Array(String, Object)>] the `[name, chapter]`
105
- # pairs `call` last cached against
106
- # @param current [Array<Array(String, Object)>] the registry's
107
- # current `[name, chapter]` pairs
108
- # @return [Boolean] whether `cached` and `current` name the same
109
- # chapters, by identity, in the same order
36
+ # `equal?`, not `==` — chapter identity, not value equality, is the
37
+ # fact this cache key tracks.
110
38
  def same_chapters?(cached, current)
111
39
  cached.size == current.size &&
112
40
  cached.zip(current).all? do |(cached_name, cached_chapter), (name, chapter)|
@@ -114,73 +42,17 @@ module Hecks
114
42
  end
115
43
  end
116
44
 
117
- # Cross-process persistence for the same ~1s-per-build work `call`
118
- # above already memoizes in-process — this file's own chapter-
119
- # identity keying only ever helps callers sharing one process (the
120
- # in-memory fixpoint window, or `bin/reference`'s single run); every
121
- # fresh process (a `qa_sweep --all` child, a `parallel_rspec`
122
- # worker, `bin/qa_sweep` itself) pays both real builds again from
123
- # scratch even when the grammar source hasn't changed at all since
124
- # the last process that built it.
125
- #
126
- # Not a fix for the two-builds-per-process shape — investigated and
127
- # confirmed genuine, not waste (see this module's own header
128
- # history: the previous "wait for the whole registry" design cost
129
- # 42 rebuilds/32s per process precisely because real callers need a
130
- # correct table mid-bootstrap, before Paging attaches). Both builds
131
- # still happen once each per process; this only makes each of them
132
- # a cheap disk read instead of a real ~1s dispatch, once some
133
- # earlier process has already paid for that exact chapter-set +
134
- # grammar-content combination.
135
- #
136
- # Keyed the same way `same_chapters?` is, translated across process
137
- # boundaries — chapter *object identity* (what the in-memory cache
138
- # keys on) means nothing to a different process; chapter *names*,
139
- # in the same order, do. Combined with a content hash of every
140
- # grammar file `boot` can read from (`seed_chapters` walks every
141
- # bluebook the registry holds, so this must cover the core chapters
142
- # and every attached one, not just "Bluebook" + "Paging") — a
143
- # source edit anywhere in that set correctly misses the old cache
144
- # entry rather than silently serving a stale table.
145
- #
146
- # Fails toward a real boot, never toward a wrong table — same
147
- # loud-not-silent discipline this codebase already holds CI to
148
- # (`postgres_io_relevant_changed`'s own header). A missing file, a
149
- # corrupt Marshal blob, a permission error, an unwritable `tmp/` —
150
- # every one of these degrades to "no disk cache today", never to a
151
- # crash or a served-but-wrong table. `tmp/` is already gitignored
152
- # for exactly this kind of local, disposable-but-useful-while-it-
153
- # lasts artifact (`Storehouse::LOG_ROOT`'s own header names the
154
- # same convention).
155
- #
156
- # **Atomic write, not a lock** — `qa_sweep --all` spawns up to 4
157
- # children at once, any of which could reach a cold cache
158
- # simultaneously and each compute the identical real boot result
159
- # for the identical key. Writing to a PID-suffixed temp file and
160
- # `File.rename`ing it into place (a single atomic syscall on the
161
- # same filesystem) means a concurrent second writer's rename just
162
- # overwrites the first with byte-identical content — never a torn
163
- # or partially-written file a concurrent reader could observe.
164
- #
165
- # `HECKS_SYNTAX_BOOT_CACHE=off` — an escape hatch needing no code
166
- # change, the same shape `Storehouse::BOOT_ROOT`'s own
167
- # `HECKS_STOREHOUSE_ROOT` override uses, for the day this needs to
168
- # be ruled out while debugging something else entirely.
169
- CACHE_DIR = File.expand_path("../../../../tmp/hecks_syntax_boot_cache", __dir__).freeze
45
+ # Cross-process persistence for the same build `call` already memoizes
46
+ # in-process, keyed by chapter name (not identity, which means nothing
47
+ # across processes) plus a content hash of every grammar file `boot`
48
+ # can read from — so a source edit anywhere in that set misses the
49
+ # cache rather than silently serving a stale table.
50
+ def cache_dir = Hecks::CacheDir.path("hecks_syntax_boot_cache")
170
51
 
171
- # Reports whether the cross-process disk cache is turned on.
172
- #
173
- # @return [Boolean] whether the cross-process disk cache is turned
174
- # on (`HECKS_SYNTAX_BOOT_CACHE=off` turns it off)
175
52
  def disk_cache_enabled? = ENV["HECKS_SYNTAX_BOOT_CACHE"] != "off"
176
53
 
177
- # Reads an already-written cache entry for `chapters`, if any.
178
- #
179
- # @param chapters [Array<Array(String, Object)>] the `[name,
180
- # chapter]` pairs to key the cache entry on
181
- # @return [Hash{Symbol => Array<Hash{Symbol => String}>}, nil] the
182
- # cached syntax table, or `nil` if the cache is disabled, no entry
183
- # exists yet, or the entry could not be read
54
+ # Fails toward a real boot, never toward a wrong table: a missing
55
+ # file, a corrupt blob, or a permission error just misses the cache.
184
56
  def read_disk_cache(chapters)
185
57
  return nil unless disk_cache_enabled?
186
58
 
@@ -192,18 +64,14 @@ module Hecks
192
64
  nil
193
65
  end
194
66
 
195
- # Writes `result` to the disk cache for `chapters`, atomically.
196
- #
197
- # @param chapters [Array<Array(String, Object)>] the `[name,
198
- # chapter]` pairs to key the cache entry on
199
- # @param result [Hash{Symbol => Array<Hash{Symbol => String}>}] the
200
- # syntax table to persist
201
- # @return [void]
67
+ # Writes to a PID-suffixed temp file and renames it into place, so a
68
+ # concurrent writer's rename can only overwrite with identical
69
+ # content, never leave a torn file for a concurrent reader.
202
70
  def write_disk_cache(chapters, result)
203
71
  return unless disk_cache_enabled?
204
72
 
205
73
  path = disk_cache_path(chapters)
206
- FileUtils.mkdir_p(CACHE_DIR)
74
+ FileUtils.mkdir_p(cache_dir)
207
75
  tmp_path = "#{path}.#{Process.pid}.tmp"
208
76
  File.binwrite(tmp_path, Marshal.dump(result))
209
77
  File.rename(tmp_path, path)
@@ -211,38 +79,18 @@ module Hecks
211
79
  nil
212
80
  end
213
81
 
214
- # Builds the disk cache file path for `chapters`.
215
- #
216
- # @param chapters [Array<Array(String, Object)>] the `[name,
217
- # chapter]` pairs to key the cache entry on
218
- # @return [String] the disk cache file path for `chapters`
219
82
  def disk_cache_path(chapters)
220
- File.join(CACHE_DIR, "#{disk_cache_key(chapters)}.marshal")
83
+ File.join(cache_dir, "#{disk_cache_key(chapters)}.marshal")
221
84
  end
222
85
 
223
- # Builds the cache key for `chapters`.
224
- #
225
- # @param chapters [Array<Array(String, Object)>] the `[name,
226
- # chapter]` pairs to key the cache entry on
227
- # @return [String] a SHA-256 digest of the chapter names and the
228
- # current grammar source
229
86
  def disk_cache_key(chapters)
230
87
  names = chapters.map { |name, _chapter| name }
231
88
  Digest::SHA256.hexdigest("#{names.join(',')}:#{grammar_content_digest}")
232
89
  end
233
90
 
234
- # Every file `boot` can possibly read from, via `seed_chapters`
235
- # walking every bluebook the registry holds — not just "Bluebook"
236
- # and "Paging" (the two chapters this module's own comments name
237
- # most often), because World/Hecksagon/any future attached chapter
238
- # are equally eligible to carry their own `KeywordSeed`/
239
- # `ArgumentSeed` value object. Coarser than strictly necessary (any
240
- # one file changing invalidates every cached key, not just the
241
- # chapter it belongs to) — deliberately, since under-covering this
242
- # set is a correctness bug (a stale table survives a real grammar
243
- # edit) and over-covering it is only ever a wasted cache miss.
244
- # @return [String] a SHA-256 digest of every grammar file's own
245
- # current content, sorted for a stable digest
91
+ # Covers every chapter's grammar files, not just the core ones —
92
+ # coarser than strictly necessary, but under-covering this set would
93
+ # let a stale table survive a real grammar edit.
246
94
  def grammar_content_digest
247
95
  files = (MetaValidator::GRAMMAR_FILES + MetaValidator::WORLD_GRAMMAR + MetaValidator::HECKSAGON_GRAMMAR +
248
96
  Dir.glob(File.join(MetaValidator::ATTACHED_GRAMMAR_DIR, "*.bluebook"))).sort
@@ -251,21 +99,11 @@ module Hecks
251
99
 
252
100
  # Dispatches every seed row into a fresh "Bluebook" instance and
253
101
  # reads the result back.
254
- #
255
- # @return [Hash{Symbol => Array<Hash{Symbol => String}>}] `:keywords`
256
- # and `:arguments`, each an array of plain, string-valued row
257
- # hashes (`status` included)
258
102
  def boot
259
103
  bluebook = MetaValidator.grammar_registry.bluebook("Bluebook")
260
- # `MetaValidator.fresh_runtime`, not a brand-new `Runtime::
261
- # Registry` — the grammar registry's own copy already has
262
- # "Bluebook" registered (`grammar_registry`'s own boot already
263
- # ran `registry.add_bluebook`) and its adapter ports already
264
- # loaded ; a standalone registry would need both wired by hand.
265
- # `fresh_runtime` resets `@repositories` on the same registry —
266
- # the identical isolation `Judge.new` already relies on for
267
- # every real domain it judges, proven safe by every dispatch
268
- # this session has ever made.
104
+ # `fresh_runtime`, not a new `Runtime::Registry` — the grammar
105
+ # registry already has "Bluebook" registered and its adapter
106
+ # ports already loaded.
269
107
  runtime = MetaValidator.fresh_runtime
270
108
 
271
109
  declare_syntax(runtime, bluebook)
@@ -275,56 +113,26 @@ module Hecks
275
113
  read_back(runtime, bluebook)
276
114
  end
277
115
 
278
- # Wraps `text` as a single-field value-object payload, for a
279
- # dispatch's own `with:`.
280
- #
281
- # An Integer stays an Integer — `position` is `Position`-typed
282
- # (`attribute :value, Integer`), so stringifying it fails the type
283
- # gate rather than feeding it, the same reading `Judge#v` gives.
284
- #
285
- # @param text [String, Integer] the scalar to wrap
286
- # @return [Hash{Symbol => String, Integer}] `{value: text}`,
287
- # stringified unless `text` is already an Integer
116
+ # An Integer stays an Integer — `position` is `Position`-typed, so
117
+ # stringifying it would fail the type gate rather than feed it.
288
118
  def v(text)
289
119
  return { value: text } if text.is_a?(Integer)
290
120
 
291
121
  { value: text.to_s }
292
122
  end
293
123
 
294
- # Wraps `text` as an `optional: true` command argument's own
295
- # payload, or omits it.
296
- #
297
- # Absent stays absent. A seed row's own optional columns ("was",
298
- # "at", "named", ...) are empty strings, not nil — `Literal`/CSV-
299
- # shaped grammar data has no `nil` to write — so this is the one
300
- # place that decides "" means "not given" for the purpose of an
301
- # `optional: true` command argument, the same reading `Judge#v`
302
- # makes for the meta-domain's own dispatches.
303
- #
304
- # @param text [String, nil] the seed row's own column value
305
- # @return [Hash{Symbol => String}, nil] `v(text)`, or `nil` when
306
- # `text` is `nil` or empty
124
+ # A seed row's own optional columns are "", not nil (CSV-shaped
125
+ # grammar data has no nil to write) — this is where "" is read as
126
+ # "not given".
307
127
  def optional(text)
308
128
  return nil if text.nil? || text.to_s.empty?
309
129
 
310
130
  v(text)
311
131
  end
312
132
 
313
- # `Syntax.Declare`'s own `reference_to Bluebook` names the chapter
314
- # it belongs to — the same fact every other top-level aggregate's
315
- # own creating command carries (`ProcessManager.Declare`,
316
- # `Policy.Declare`, ...). This fresh runtime holds no chapter
317
- # record of its own yet (nothing else here needs one), so one is
318
- # declared first, named after the real chapter, purely to satisfy
319
- # the reference — its own vision/classification are never read
320
- # by anything this boot does.
321
- #
322
- # @param runtime [Runtime::Dispatcher] the fresh runtime to
323
- # dispatch into
324
- # @param bluebook [Bluebook::Chapter] the language's own assembled
325
- # "Bluebook" chapter, read for its `hecks_name` and `"Syntax"`
326
- # aggregate
327
- # @return [void]
133
+ # This fresh runtime holds no chapter record of its own, so one is
134
+ # declared first, purely to satisfy `Syntax.Declare`'s `reference_to
135
+ # Bluebook` — its vision/classification are never read afterward.
328
136
  def declare_syntax(runtime, bluebook)
329
137
  syntax = bluebook.aggregate("Syntax")
330
138
  runtime.dispatch("Bluebook::Bluebook.Declare",
@@ -336,21 +144,10 @@ module Hecks
336
144
  with: { bluebook: bluebook.hecks_name, name: v(syntax.hecks_name) })
337
145
  end
338
146
 
339
- # `to: "Syntax"` names the record already opened by `declare_syntax`
340
- # above — an append onto an existing aggregate, not a second creation
341
- # of it. Smuggling `name: v("Syntax")` into the payload instead — the
342
- # pre-routing convention `Judge#appends` (the same append shape, for
343
- # `ValueObject.Member`/`ProcessManager.Handler`) already left behind
344
- # for `to:`/`with:` — would carry the receiver in the payload,
345
- # making `Syntax.Keyword`'s own `command.creates?` (true: it
346
- # declares no `reference_to`) look like a fresh identity to mint,
347
- # colliding with the very "Syntax" row `declare_syntax` just opened.
348
- #
349
- # @param runtime [Runtime::Dispatcher] the fresh runtime to
350
- # dispatch into
351
- # @param bluebook [Bluebook::Chapter] the language's own assembled
352
- # "Bluebook" chapter, read for its `KeywordSeed` rows
353
- # @return [void]
147
+ # `to: "Syntax"` appends onto the record `declare_syntax` already
148
+ # opened; putting the receiver in the payload instead would make
149
+ # `Syntax.Keyword` look like a fresh identity to mint, colliding
150
+ # with that row.
354
151
  def admit_keywords(runtime, bluebook)
355
152
  all_rows(bluebook, "KeywordSeed").each_with_index do |row, index|
356
153
  runtime.dispatch("Bluebook::Syntax.Keyword", to: "Syntax",
@@ -368,14 +165,7 @@ module Hecks
368
165
  end
369
166
  end
370
167
 
371
- # Admits every `ArgumentSeed` row as a `Syntax.Argument`, the same
372
- # `to: "Syntax"` append shape `admit_keywords` uses one type over.
373
- #
374
- # @param runtime [Runtime::Dispatcher] the fresh runtime to
375
- # dispatch into
376
- # @param bluebook [Bluebook::Chapter] the language's own assembled
377
- # "Bluebook" chapter, read for its `ArgumentSeed` rows
378
- # @return [void]
168
+ # Same `to: "Syntax"` append shape `admit_keywords` uses, one type over.
379
169
  def admit_arguments(runtime, bluebook)
380
170
  all_rows(bluebook, "ArgumentSeed").each_with_index do |row, index|
381
171
  runtime.dispatch("Bluebook::Syntax.Argument", to: "Syntax",
@@ -395,49 +185,18 @@ module Hecks
395
185
  end
396
186
  end
397
187
 
398
- # Every aggregate-local table in every loaded language chapter.
399
- # The table's presence is the registration: no chapter, aggregate,
400
- # filename, or context catalog is maintained here. This finds the core
401
- # Bluebook concepts, the sibling artifact languages (World, Hecksagon,
402
- # Port, Adapter, Translation), and attached sub-languages alike.
403
- # Concatenated into one sequence because `position` is minted from the
404
- # walk index and must not collide across concepts.
405
- #
406
- # @param bluebook [Bluebook::Chapter] the language's own assembled
407
- # "Bluebook" chapter, read first, before every other loaded
408
- # chapter
409
- # @param name [String] the local value-object name to collect rows
410
- # of, such as `"KeywordSeed"`
411
- # @return [Array<Hash{Symbol => String}>] every matching row, across
412
- # every loaded chapter, in chapter order
188
+ # Concatenated into one sequence because `position` is minted from
189
+ # the walk index and must not collide across concepts.
413
190
  def all_rows(bluebook, name)
414
191
  seed_chapters(bluebook).flat_map { |chapter| rows(chapter, name) }
415
192
  end
416
193
 
417
- # Keep the core chapter first, then registry insertion order for every
418
- # sibling/extension. The name rejection avoids reading the same core
419
- # object twice without relying on object identity across fixpoint
420
- # assembly.
421
- #
422
- # @param bluebook [Bluebook::Chapter] the language's own assembled
423
- # "Bluebook" chapter
424
- # @return [Array<Bluebook::Chapter>] `bluebook` first, then every
425
- # other chapter the grammar registry holds
194
+ # `bluebook` first, then registry insertion order, so the core
195
+ # chapter is never read twice.
426
196
  def seed_chapters(bluebook)
427
197
  [bluebook] + MetaValidator.grammar_registry.bluebooks.values.reject { |chapter| chapter.name == bluebook.name }
428
198
  end
429
199
 
430
- # The seed rows themselves — plain hashes, string values, read from
431
- # every aggregate that owns a same-named local value object. Repeating
432
- # the value-object shape is deliberate: each concept remains readable
433
- # by itself, while this discovery is the only grouping mechanism.
434
- #
435
- # @param bluebook [Bluebook::Chapter] the chapter to search
436
- # @param name [String] the local value-object name to collect rows
437
- # of, such as `"KeywordSeed"`
438
- # @return [Array<Hash{Symbol => String}>] one hash per member row,
439
- # `[]` if no aggregate in `bluebook` owns a value object named
440
- # `name`
441
200
  def rows(bluebook, name)
442
201
  bluebook.aggregates.flat_map do |aggregate|
443
202
  value_object = aggregate.value_objects.find { |vo| vo.hecks_name == name }
@@ -447,18 +206,8 @@ module Hecks
447
206
  end
448
207
  end
449
208
 
450
- # Reads the dispatched result back into the same shape `rows`
451
- # above hands the seed data in as — plain hashes, string values,
452
- # `status` included — so `ParserTable`/`syntax_conformance_spec`
453
- # need not know or care that a real dispatch happened in between.
454
- #
455
- # @param runtime [Runtime::Dispatcher] the runtime `boot` dispatched
456
- # every seed row into
457
- # @param bluebook [Bluebook::Chapter] the language's own assembled
458
- # "Bluebook" chapter, read for its `"Syntax"` aggregate
459
- # @return [Hash{Symbol => Array<Hash{Symbol => String}>}] `:keywords`
460
- # and `:arguments`, each an array of plain, string-valued row
461
- # hashes (`status` included)
209
+ # Reads the dispatched result back into the same plain-hash shape
210
+ # `rows` hands the seed data in as.
462
211
  def read_back(runtime, bluebook)
463
212
  syntax = bluebook.aggregate("Syntax")
464
213
  repository = runtime.registry.repository("Bluebook", syntax)
@@ -470,23 +219,13 @@ module Hecks
470
219
  }
471
220
  end
472
221
 
473
- # Flattens one dispatched record into a plain, string-valued row.
474
- #
475
- # @param row [Object] one dispatched keyword or argument record,
476
- # answering `to_h`
477
- # @return [Hash{Symbol => String}] `row`'s own fields, each value
478
- # unwrapped and stringified
479
222
  def stringify(row)
480
223
  row.to_h.transform_values do |cell|
481
224
  scalar(cell).to_s
482
225
  end
483
226
  end
484
227
 
485
- # Unwraps one field's stored value to its bare scalar.
486
- #
487
- # @param cell [Object] one field's stored value
488
- # @return [Object] `cell`'s sole wrapped value, if `cell` is a
489
- # to_h-able non-String; `cell` unchanged otherwise
228
+ # Unwraps a value-object-wrapped field back to its bare scalar.
490
229
  def scalar(cell)
491
230
  return cell.to_h.values.first if cell.respond_to?(:to_h) && !cell.is_a?(String)
492
231
 
@@ -1,24 +1,8 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module MetaValidator
4
- # Offers a built translation (a `translations/*.bluebook` edge,
5
- # `Hecks.data_translation`'s own real, established file convention —
6
- # there is no separate `.translation` extension) to the language
7
- # that describes translations.
8
- #
9
- # A sibling of a bluebook again, the same shape PortJudge/
10
- # AdapterJudge already are — its own file, its own door, judged
11
- # through its own self-hosted language (translation.bluebook)
12
- # rather than left as plain Ruby structs nothing checks. Walks the
13
- # whole built translation in one pass — the top-level Declare/
14
- # Retire commands, then every nested aggregate's own Declare plus
15
- # one Add* command per rule it carries — the same "one judge, every
16
- # nested record" shape WorldJudge already gives Wiring. Field names
17
- # throughout read lib/hecks/bluebook/translation.rb's own real
18
- # struct/class definitions directly, not the DSL builder's own
19
- # local parameter names (`move(old_path, to:)`'s `old_path` reads
20
- # back as the struct's own `from`). Whole-project table-
21
- # unification survey, item #13's remaining builders.
4
+ # Offers a built translation (a `translations/*.bluebook` edge) to the language that
5
+ # describes translations. Field names follow the `Translation` structs, not the DSL builder.
22
6
  class TranslationJudge
23
7
  attr_reader :refusals
24
8
 
@@ -36,18 +20,8 @@ module Hecks
36
20
 
37
21
  def args(pairs) = pairs.compact
38
22
 
39
- # `Runtime::AlreadyExists` is rescued here but not by World/Port/
40
- # Adapter's own sibling judges — found live, not by inspection.
41
- # Those three each judge a single aggregate per build (Port/Adapter)
42
- # or a Hash keyed by verb (World's own settings, deduped by
43
- # construction), so a duplicate-identity Declare can never reach
44
- # their own runtime. `TranslationBuilder#aggregate` appends every
45
- # block to a plain Array (`@aggregates << builder.build`) with no
46
- # dedup — two `aggregate "Account" do ... end` blocks in the same
47
- # translation are syntactically legal and reach here for real.
48
- # Left unrescued, the second Declare's `AlreadyExists` would crash
49
- # straight through `call_translation` instead of becoming a clean
50
- # refusal — confirmed via direct dispatch.
23
+ # Rescues `AlreadyExists` too: `TranslationBuilder#aggregate` does not dedup, so two
24
+ # same-named aggregate blocks reach here and must become a refusal, not a crash.
51
25
  def offer(label)
52
26
  yield
53
27
  rescue Runtime::GivenNotMet, Runtime::InvariantViolation, Runtime::TypeMismatch,
@@ -66,14 +40,7 @@ module Hecks
66
40
  send_to("Translation::Translation.Declare", t.domain,
67
41
  with: { domain: v(t.domain), from: v(t.from), to: v(t.to) })
68
42
 
69
- # `id:`, computed the same way — `Naming.identity([domain, from,
70
- # to])` — Translation's own identity is composite
71
- # (`identified_by :domain, :from, :to`), the same reason
72
- # `Wiring.Set`'s own self-reference dispatch (world.bluebook,
73
- # `WorldJudge#judge_wiring`) needs a computed `id:` rather than
74
- # a bare field value — a single-field identity (TranslationAggregate's
75
- # own `name`) is the one case where the bare value itself is the
76
- # id, confirmed live via direct dispatch testing, not assumed.
43
+ # Translation's identity is composite, so `id:` must be computed, not a bare field.
77
44
  translation_id = Naming.identity([t.domain, t.from, t.to])
78
45
  Array(t.retired).each do |name|
79
46
  send_to("Translation::Translation.Retire", t.domain, to: translation_id,
@@ -83,11 +50,8 @@ module Hecks
83
50
  Array(t.aggregates).each { |aggregate| judge_aggregate(t, aggregate) }
84
51
  end
85
52
 
86
- # One Declare, then one AddX pass per rule collection the aggregate
87
- # carries — each pass is independent of the others (they mutate
88
- # different fields), so each is its own private method below; only
89
- # Declare-before-any-Add is order-sensitive, and that order is
90
- # preserved here.
53
+ # Declares the aggregate, then adds each rule collection. Only Declare-before-Add is
54
+ # order-sensitive.
91
55
  def judge_aggregate(translation, aggregate)
92
56
  name = aggregate.name
93
57
  declare_aggregate(translation, aggregate, name)
@@ -1,16 +1,11 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  module MetaValidator
4
- # Offers a built .world to the language that describes worlds.
5
- #
6
- # A world is a sibling of a bluebook — the same domain runs in many of
7
- # them — so it is judged through its own door, against its own language
8
- # file, and its settings normalise the same way a mutation's fields do:
9
- # an open map becomes one Wiring per verb and one Setting row per value.
4
+ # Judges a built .world against the language that describes worlds,
5
+ # normalizing its settings into one Wiring per verb, one Setting per value.
10
6
  class WorldJudge
11
7
  attr_reader :refusals
12
8
 
13
- # @param world [Bluebook::World] the built world to judge
14
9
  def initialize(world)
15
10
  @world = world
16
11
  @refusals = []
@@ -54,18 +49,11 @@ module Hecks
54
49
  end
55
50
 
56
51
  def judge_wiring(domain, verb, values)
57
- # The same join the language itself derives. Wiring is
58
- # `identified_by do world; verb.value end` — `Wiring.Declare`
59
- # (a creating command) ignores this `id:` entirely and computes its own
60
- # from `world`/`verb`, so a locally minted "#{domain}.#{verb}" named a
61
- # record `Wiring.Set` could never find : the id passed here has to be
62
- # the same derivation, not a second guess at what it must be.
52
+ # Must match Wiring's own `identified_by do world; verb.value end`
53
+ # derivation exactly, or a later `Wiring.Set` could never find it.
63
54
  id = Naming.identity([domain, verb])
64
- # `world_ref` is the world's id and goes bare, the way every reference
65
- # does now ; the language gives it that explicit `as:` because `world`
66
- # beside it is an ordinary text attribute that happens to hold the same
67
- # string, and stays a value object. The two look alike and are not —
68
- # which is exactly why the judge asks the type rather than the name.
55
+ # `world_ref` is the type-checked reference; the plain `world`
56
+ # attribute alongside it just happens to hold the same string.
69
57
  send_to("World::Wiring.Declare", id, world_ref: v(domain),
70
58
  world: v(domain), verb: v(verb), adapter: v(Hash(values)[:adapter]))
71
59