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
@@ -3,24 +3,8 @@ require_relative "../../forms/html"
3
3
  module Hecks
4
4
  module Projections
5
5
  module Glossary
6
- # **The page, rendered from the markdown** — `html/index.html` is
7
- # `glossary.md` read back and dressed: a navigation rail built from
8
- # its `##` headings, each `###` a term entry, every ```mermaid fence
9
- # a diagram, every `[x](#y)` an in-page link. Nothing here reads
10
- # the bluebook; if the page shows it, the Markdown says it, so the
11
- # two cannot drift.
12
- #
13
- # A subset renderer, not a markdown library — the projector emits
14
- # a fixed handful of constructs (`Markdown`'s own header lists
15
- # them), and this reads exactly those. The Gemfile keeps every
16
- # dependency justified in its own comment; a full Markdown engine
17
- # for six constructs would not earn one.
18
- #
19
- # The look lives in page.css / page.js beside this file — read at
20
- # render time and inlined, so the page is one self-contained file.
21
- # The only things it fetches are the two typefaces (Google Fonts)
22
- # and Mermaid itself (cdnjs), which draws the diagrams in the
23
- # browser; without a network the diagrams show as their source.
6
+ # Renders `glossary.md` into a self-contained HTML page with a navigation rail.
7
+ # A subset renderer for the constructs the projector emits, not a Markdown library.
24
8
  module Html
25
9
  Block = Struct.new(:type, :text, :items, :level, keyword_init: true)
26
10
 
@@ -31,9 +15,7 @@ module Hecks
31
15
  module_function
32
16
 
33
17
  # Renders `glossary.md`'s Markdown source as a self-contained HTML page.
34
- #
35
- # @param markdown [String] `glossary.md`'s own rendered Markdown source
36
- # @return [String] the complete `html/index.html` source
18
+ # Reads only the Markdown, never the bluebook, so the two cannot drift.
37
19
  def render(markdown)
38
20
  blocks = parse(markdown)
39
21
  slugs = heading_slugs(blocks)
@@ -42,14 +24,7 @@ module Hecks
42
24
  page(title, sections, slugs)
43
25
  end
44
26
 
45
- # ── reading the Markdown ─────────────────────────────────────────
46
-
47
- # Parses the subset of Markdown the glossary projector emits into
48
- # structured blocks.
49
- #
50
- # @param markdown [String] the Markdown source to parse
51
- # @return [Array<Block>] one block per heading, quote, list, mermaid
52
- # fence, or paragraph, in document order
27
+ # Parses the Markdown subset the glossary projector emits into blocks.
53
28
  def parse(markdown)
54
29
  lines = markdown.lines.map(&:chomp)
55
30
  blocks = []
@@ -78,27 +53,13 @@ module Hecks
78
53
  blocks
79
54
  end
80
55
 
81
- # The mermaid source between the opening fence at `index` and its
82
- # closing one, and the index just past that.
83
- #
84
- # @param lines [Array<String>] the document's lines
85
- # @param index [Integer] the opening ` ```mermaid ` fence's line index
86
- # @return [Array(Block, Integer)] the parsed `:mermaid` block, and the line
87
- # index just past its closing fence
56
+ # The mermaid block opened at `index`, and the line index just past its closing fence.
88
57
  def fence(lines, index)
89
58
  close = ((index + 1)...lines.size).find { |at| lines[at] == "```" } || lines.size
90
59
  [Block.new(type: :mermaid, text: lines[(index + 1)...close].join("\n")), close + 1]
91
60
  end
92
61
 
93
- # The consecutive lines from `index` that satisfy the block, and
94
- # the index just past them.
95
- #
96
- # @param lines [Array<String>] the document's lines
97
- # @param index [Integer] the line index to start scanning from
98
- # @yieldparam text [String] one candidate line
99
- # @yieldreturn [Boolean] whether that line belongs to the run
100
- # @return [Array(Array<String>, Integer)] the consecutive matching lines, and
101
- # the line index just past them
62
+ # The consecutive lines from `index` that satisfy the block, and the index past them.
102
63
  def run(lines, index)
103
64
  taken = []
104
65
  while index < lines.size && yield(lines[index])
@@ -108,17 +69,9 @@ module Hecks
108
69
  [taken, index]
109
70
  end
110
71
 
111
- # The same slugs GitHub would give these headings, in the same
112
- # order — so the links the Markdown carries land here too.
113
- #
114
- # Keyed by the block itself, not its value — a Struct compares by
115
- # members, so two "### Open" headings in different sections would
116
- # otherwise be one key, and the first would answer with the
117
- # second's "-1" slug, leaving `#open` with nothing to land on.
118
- #
119
- # @param blocks [Array<Block>] every parsed block, in document order
120
- # @return [Hash{Block => String}] each heading block, mapped to its GitHub-style
121
- # slug, keyed by object identity
72
+ # GitHub's slugs for these headings, so links the Markdown carries land here too.
73
+ # Keyed by identity: a Struct compares by members, so two "### Open" headings in
74
+ # different sections would collide and `#open` would have nothing to land on.
122
75
  def heading_slugs(blocks)
123
76
  seen = Hash.new(0)
124
77
  slugs = {}.compare_by_identity
@@ -130,13 +83,7 @@ module Hecks
130
83
  slugs
131
84
  end
132
85
 
133
- # Everything before the first `##` is the front matter; each `##`
134
- # opens a section that runs to the next.
135
- #
136
- # @param blocks [Array<Block>] every parsed block, in document order
137
- # @return [Array<Hash{Symbol => Object}>] one Hash per section: `:heading`
138
- # (the `Block`, or nil for the leading front matter) and `:blocks` (its
139
- # own `Array<Block>`)
86
+ # Blocks before the first `##` are front matter (heading nil); each `##` opens a section.
140
87
  def split_sections(blocks)
141
88
  sections = [{ heading: nil, blocks: [] }]
142
89
  blocks.each do |block|
@@ -146,15 +93,6 @@ module Hecks
146
93
  sections
147
94
  end
148
95
 
149
- # ── writing the page ─────────────────────────────────────────────
150
-
151
- # Renders the full HTML page shell around the navigation rail and content.
152
- #
153
- # @param title [String] the document's `#` heading text
154
- # @param sections [Array<Hash{Symbol => Object}>] every `##` section, as
155
- # `split_sections` builds (the front matter excluded by the caller)
156
- # @param slugs [Hash{Block => String}] every heading block's own slug
157
- # @return [String] the complete HTML page source
158
96
  def page(title, sections, slugs)
159
97
  front, *rest = sections
160
98
  <<~HTML
@@ -186,14 +124,6 @@ module Hecks
186
124
  HTML
187
125
  end
188
126
 
189
- # Renders the navigation rail: the domain name, a search box, and one
190
- # link per section.
191
- #
192
- # @param title [String] the document's `#` heading text, `"Domain — Glossary"`
193
- # @param sections [Array<Hash{Symbol => Object}>] every `##` section (the
194
- # front matter excluded)
195
- # @param slugs [Hash{Block => String}] every heading block's own slug
196
- # @return [String] the rail's HTML source
197
127
  def rail(title, sections, slugs)
198
128
  domain = title.split(" — ").first
199
129
  items = sections.map do |section|
@@ -213,10 +143,6 @@ module Hecks
213
143
  HTML
214
144
  end
215
145
 
216
- # Renders the page's `<header>`: the title, vision, lede, and overview diagram.
217
- #
218
- # @param blocks [Array<Block>] the front matter's own blocks
219
- # @return [String] the header's HTML source
220
146
  def front_matter(blocks)
221
147
  parts = ["<header>"]
222
148
  blocks.each do |block|
@@ -231,15 +157,8 @@ module Hecks
231
157
  parts.join("\n")
232
158
  end
233
159
 
234
- # A section is its heading, then its opening (lede, diagrams, the
235
- # rules list), then its terms — each `###` opens an article that
236
- # runs to the next. A bold-only paragraph is the caption of
237
- # whatever figure or list follows it.
238
- #
239
- # @param section [Hash{Symbol => Object}] one `##` section, as `split_sections`
240
- # builds
241
- # @param slugs [Hash{Block => String}] every heading block's own slug
242
- # @return [String] the section's `<section>` HTML source
160
+ # Each `###` opens an article running to the next. A bold-only paragraph
161
+ # captions whatever figure or list follows it.
243
162
  def section_html(section, slugs)
244
163
  heading = section[:heading]
245
164
  state = { parts: [%(<section id="#{slugs[heading]}">), "<h2>#{inline(heading.text)}</h2>"],
@@ -250,15 +169,7 @@ module Hecks
250
169
  state[:parts].join("\n")
251
170
  end
252
171
 
253
- # Renders one block into `state[:parts]`, mutating `state` as it goes.
254
- #
255
- # @param block [Block] the block to render
256
- # @param state [Hash{Symbol => Object}] the section's own render state:
257
- # `:parts` (the growing `Array<String>` of HTML), `:caption` (a pending
258
- # bold-only paragraph's text, or nil), `:in_terms` (whether a `###` term
259
- # article is currently open)
260
- # @param slugs [Hash{Block => String}] every heading block's own slug
261
- # @return [void]
172
+ # Renders one block into `state[:parts]`, mutating `state`.
262
173
  def section_block(block, state, slugs)
263
174
  parts = state[:parts]
264
175
  case block.type
@@ -279,13 +190,6 @@ module Hecks
279
190
  end
280
191
  end
281
192
 
282
- # Renders one paragraph, either capturing it as a pending caption (a
283
- # bold-only line) or appending it to `state[:parts]`.
284
- #
285
- # @param text [String] the paragraph's own text
286
- # @param state [Hash{Symbol => Object}] the section's own render state (see
287
- # `section_block`); `:caption` and `:parts` may be mutated
288
- # @return [void]
289
193
  def paragraph(text, state)
290
194
  if text.match?(/\A\*\*[^*]+\*\*\z/)
291
195
  state[:caption] = text.delete("*")
@@ -295,11 +199,6 @@ module Hecks
295
199
  end
296
200
  end
297
201
 
298
- # Renders a mermaid block as a `<figure>`, with an optional caption.
299
- #
300
- # @param block [Block] the `:mermaid` block to render
301
- # @param caption [String, nil] the figure's caption text, or nil for none
302
- # @return [String] the `<figure>`'s HTML source
303
202
  def figure(block, caption)
304
203
  parts = ["<figure>"]
305
204
  parts << "<figcaption>#{escape(caption)}</figcaption>" if caption
@@ -307,20 +206,9 @@ module Hecks
307
206
  parts.join("\n")
308
207
  end
309
208
 
310
- # ── inline text ──────────────────────────────────────────────────
311
-
312
- # Escapes text for HTML.
313
- #
314
- # @param text [Object, nil] the value to escape, rendered with `to_s`
315
- # @return [String] `text`, HTML-escaped
316
209
  def escape(text) = Forms::Escape.html(text)
317
210
 
318
- # Escape first, so nothing in the prose ever becomes a tag; then
319
- # the three inline forms the Markdown uses, on the escaped text.
320
- #
321
- # @param text [String] the inline text to render
322
- # @return [String] `text`, HTML-escaped, with `[x](#y)` links, `**bold**` and
323
- # `*italic*` spans converted to their HTML equivalents
211
+ # Escapes first so prose never becomes a tag, then converts links, bold and italic.
324
212
  def inline(text)
325
213
  escape(text)
326
214
  .gsub(/\[([^\]]+)\]\(#([^)]+)\)/) { %(<a href="##{Regexp.last_match(2)}">#{Regexp.last_match(1)}</a>) }
@@ -328,10 +216,6 @@ module Hecks
328
216
  .gsub(/\*(.+?)\*/) { "<em>#{Regexp.last_match(1)}</em>" }
329
217
  end
330
218
 
331
- # Reads one static asset file from beside this file.
332
- #
333
- # @param name [String] the asset's filename, such as `"page.css"`
334
- # @return [String] the asset file's contents, read from beside this file
335
219
  def asset(name) = File.read(File.join(__dir__, name))
336
220
  end
337
221
  end
@@ -7,25 +7,8 @@ require_relative "../statements"
7
7
  module Hecks
8
8
  module Projections
9
9
  module Glossary
10
- # **The document itself** — `glossary.md`, the one source the page is
11
- # rendered from. Written in the handful of Markdown constructs
12
- # GitHub renders as-is (headings, blockquotes, ```mermaid fences,
13
- # lists, in-page links), so the file is a complete, readable
14
- # glossary on its own before any page is built from it:
15
- #
16
- # # Banking — Glossary
17
- # > vision
18
- # lede
19
- # ```mermaid the map
20
- # ## Account
21
- # > description
22
- # Starts out open. Can be open, frozen, or closed.
23
- # **How it fits** ```mermaid
24
- # **How it moves** ```mermaid
25
- # **Always true** - one sentence per declared fact
26
- # ### Account number one ### per term, A to Z
27
- # Made up of a value (text).
28
- # Always true: an account number is present.
10
+ # Renders `glossary.md`, the source the glossary page is built from.
11
+ # Uses only Markdown that GitHub renders as-is, so the file reads on its own.
29
12
  module Markdown
30
13
  LEDE = "Every term %<name>s uses, in the words of the people who work in it — grouped under the thing " \
31
14
  "each belongs to, and listed A to Z within it. This page is generated from the working " \
@@ -41,9 +24,6 @@ module Hecks
41
24
  module_function
42
25
 
43
26
  # Titles the document after its chapter.
44
- #
45
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter to title after
46
- # @return [String] the document's `#` heading text
47
27
  def title(bluebook) = "#{bluebook.name} — Glossary"
48
28
 
49
29
  # Renders the full `glossary.md` document.
@@ -56,11 +36,7 @@ module Hecks
56
36
  "#{parts.join("\n\n")}\n"
57
37
  end
58
38
 
59
- # Renders the document's title, vision blockquote, lede, and overview map.
60
- #
61
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter to render a
62
- # header for
63
- # @return [String] the header's Markdown source
39
+ # Renders the title, vision blockquote, lede, and overview map.
64
40
  def header(bluebook)
65
41
  parts = ["# #{title(bluebook)}"]
66
42
  parts << "> #{bluebook.vision}" if bluebook.vision
@@ -69,13 +45,7 @@ module Hecks
69
45
  parts.join("\n\n")
70
46
  end
71
47
 
72
- # Renders one `##` section: its opening (an aggregate's, or a standing
73
- # group's blurb), followed by every term inside it.
74
- #
75
- # @param section [Glossary::Section] the section to render
76
- # @param document [Glossary::Document] the document `section` belongs to,
77
- # for its bluebook and link index
78
- # @return [String] the section's Markdown source
48
+ # Renders one `##` section: its opening, then every term inside it.
79
49
  def section_text(section, document)
80
50
  parts = ["## #{section.title}"]
81
51
  parts += if section.aggregate
@@ -88,16 +58,7 @@ module Hecks
88
58
  parts.join("\n\n")
89
59
  end
90
60
 
91
- # What an aggregate is, what it can be, how it fits and moves,
92
- # and what is always true of it — before a single term.
93
- #
94
- # @param aggregate [Bluebook::Aggregate] the aggregate to render an opening for
95
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter `aggregate` belongs
96
- # to, for drawing its context diagram
97
- # @param marked [Array<Hash{Symbol => String}>] the markings that flag
98
- # `aggregate`'s own fields sensitive, listed after its rules
99
- # @return [Array<String>] the opening's Markdown blocks, one per paragraph or
100
- # diagram, not yet joined
61
+ # An aggregate's opening: what it is, how it fits and moves, what is always true.
101
62
  def opening(aggregate, bluebook, marked = [])
102
63
  parts = []
103
64
  parts << "> #{aggregate.description}" if aggregate.description
@@ -113,19 +74,9 @@ module Hecks
113
74
  parts
114
75
  end
115
76
 
116
- # The statements projection's own sentences, spoken. An invariant
117
- # is the author's words and stays exactly so. A relationship
118
- # sentence is built mechanically from construct names ("An
119
- # ATMCard references an Account."), and a construct name is the
120
- # one thing this page never shows as an identifier — so each is
121
- # replaced with how it is said, whole-word, and nothing else in
122
- # the sentence is touched.
123
- #
124
- # @param aggregate [Bluebook::Aggregate] the aggregate to gather rules for
125
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter to read every
126
- # construct name from, for de-identifying relationship sentences
127
- # @return [Array<String>] `aggregate`'s (and its entities') attribute and
128
- # invariant statements, spoken and deduplicated
77
+ # The statements projection's sentences for `aggregate` and its entities, spoken.
78
+ # Invariants stay verbatim; construct names in other sentences are replaced with
79
+ # how they are said, because this page never shows an identifier.
129
80
  def always_true(aggregate, bluebook)
130
81
  names = bluebook.aggregates.flat_map { |other| [other.hecks_name, *other.entities.map(&:hecks_name)] }
131
82
  [aggregate, *aggregate.entities].flat_map do |holder|
@@ -135,28 +86,16 @@ module Hecks
135
86
  end
136
87
 
137
88
  # Replaces every whole-word construct name in `sentence` with how it is said.
138
- #
139
- # @param sentence [String] the sentence to de-identify
140
- # @param names [Array<String>] every construct name to replace, whole-word
141
- # @return [String] `sentence` with each name in `names` replaced by
142
- # `Naming.words(name)`
143
89
  def spoken(sentence, names)
144
90
  names.reduce(sentence) { |text, name| text.gsub(/\b#{Regexp.escape(name)}\b/, Naming.words(name)) }
145
91
  end
146
92
 
147
93
  # Renders one term's `###` heading and its paragraphs.
148
- #
149
- # @param entry [Glossary::Entry] the term to render
150
- # @param index [Glossary::Index] the document's link index
151
- # @return [String] the term's Markdown source
152
94
  def term_text(entry, index)
153
95
  ["### #{entry.headword}", *Sentences.paragraphs(entry, index)].join("\n\n")
154
96
  end
155
97
 
156
98
  # Wraps a Mermaid diagram's source in a fenced code block.
157
- #
158
- # @param source [String] a Mermaid diagram's own source
159
- # @return [String] `source` wrapped in a ` ```mermaid ` fence
160
99
  def fence(source) = "```mermaid\n#{source}\n```"
161
100
  end
162
101
  end
@@ -3,31 +3,13 @@ require_relative "../../naming"
3
3
  module Hecks
4
4
  module Projections
5
5
  module Glossary
6
- # The three pictures the glossary draws, each kept to the handful of
7
- # things that matter — Evans' "three to five objects central to the
8
- # issue at hand", never the whole model at once.
9
- #
10
- # map the aggregates and which points at which — one small
11
- # graph at the top, for the reader who wants the shape
12
- # of the domain before its words.
13
- # context one aggregate, its entities, and the neighbours it
14
- # points at or is pointed at by. Value objects are
15
- # words in the text ("Made up of …"), not boxes here —
16
- # Account alone has eight, and eight boxes say less
17
- # than one sentence.
18
- # lifecycle the states a thing can be in and what moves it.
19
- #
20
- # Every label is a person's spelling (`Naming.words`), and the
21
- # edges read from the same declared facts `Projections::Diagrams`
22
- # draws its own from (`reference?`, `type.target_name`, `name`,
23
- # `lifecycle.transitions`) — a different picture of the same
24
- # declaration, not a second declaration.
6
+ # The glossary's three diagrams: the map, one aggregate's context, and a lifecycle.
7
+ # Value objects appear as words in the text, not as boxes, to keep diagrams small.
25
8
  module Mermaid
26
9
  module_function
27
10
 
28
11
  # Draws the whole chapter's aggregates and which points at which.
29
12
  #
30
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter to draw
31
13
  # @return [String] a Mermaid `flowchart LR` source
32
14
  def map(bluebook)
33
15
  names = bluebook.aggregates.map(&:hecks_name)
@@ -45,9 +27,6 @@ module Hecks
45
27
 
46
28
  # Draws one aggregate, its entities, and its neighbours.
47
29
  #
48
- # @param aggregate [Bluebook::Aggregate] the aggregate to focus on
49
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter to find
50
- # neighbouring aggregates in
51
30
  # @return [String] a Mermaid `flowchart LR` source
52
31
  def context(aggregate, bluebook)
53
32
  focus = aggregate.hecks_name
@@ -70,8 +49,6 @@ module Hecks
70
49
 
71
50
  # Draws the states a holder can be in and what moves it between them.
72
51
  #
73
- # @param holder [Bluebook::Aggregate, Bluebook::Entity] the holder whose
74
- # lifecycle to draw
75
52
  # @return [String] a Mermaid `stateDiagram-v2` source
76
53
  def lifecycle(holder)
77
54
  lifecycle = holder.lifecycle
@@ -87,35 +64,17 @@ module Hecks
87
64
  lines.join("\n")
88
65
  end
89
66
 
90
- # ── the facts drawn ──────────────────────────────────────────────
91
-
92
- # Names a holder's own reference attributes.
93
- #
94
- # @param holder [Bluebook::Aggregate, Bluebook::Entity] the holder to
95
- # read reference attributes from
96
- # @return [Array<Bluebook::Attribute>] `holder`'s own reference attributes
97
67
  def references(holder) = holder.attributes.select(&:reference?)
98
68
 
99
- # An entity is held as `list_of(LedgerEntry)` — the attribute
100
- # whose element type names one of the aggregate's own entities.
101
- #
102
- # @param aggregate [Bluebook::Aggregate] the aggregate to read entity
103
- # attributes from
104
- # @return [Array<Bluebook::Attribute>] attributes whose element type is one
105
- # of `aggregate`'s own entities
69
+ # An entity is held as `list_of(LedgerEntry)`: an attribute whose element type
70
+ # names one of the aggregate's own entities.
106
71
  def entities(aggregate)
107
72
  names = aggregate.entities.map(&:hecks_name)
108
73
  aggregate.attributes.select { |attribute| !attribute.reference? && names.include?(attribute.type.to_s) }
109
74
  end
110
75
 
111
- # Finds every other aggregate that references `aggregate`.
112
- #
113
- # @param aggregate [Bluebook::Aggregate] the aggregate to find pointers to
114
- # @param bluebook [Bluebook::Behaviour::Chapter] the chapter to search other
115
- # aggregates in
116
- # @return [Array<Array(Bluebook::Aggregate, Bluebook::Attribute)>] every other
117
- # aggregate's own reference attribute that targets `aggregate`, paired
118
- # with its holder
76
+ # Finds every other aggregate's reference attribute that targets `aggregate`,
77
+ # as `[holder, attribute]` pairs.
119
78
  def pointing_at(aggregate, bluebook)
120
79
  bluebook.aggregates.reject { |other| other.equal?(aggregate) }.flat_map do |other|
121
80
  references(other).select { |attribute| attribute.type.target_name == aggregate.hecks_name }
@@ -123,32 +82,16 @@ module Hecks
123
82
  end
124
83
  end
125
84
 
126
- # ── the drawing ──────────────────────────────────────────────────
127
-
128
- # A node id the page source can carry without an identifier in
129
- # it — `n_atm_card`, never `n_ATMCard`.
130
- #
131
- # @param name [String, Symbol] the construct name to derive an id from
132
- # @return [String] a Mermaid-safe node id, such as `"n_atm_card"`
85
+ # A node id that carries no identifier: `n_atm_card`, never `n_ATMCard`.
133
86
  def id(name) = "n_#{Naming.snake(name).gsub(/[^a-z0-9_]/, '_')}"
134
87
 
135
- # Renders one Mermaid node declaration.
136
- #
137
- # @param name [String, Symbol] the node's construct name
138
- # @param focus [Boolean] whether to mark this node with the `focus` CSS class
139
- # @return [String] a Mermaid node declaration line
88
+ # Renders one Mermaid node declaration, marked `focus` when asked.
140
89
  def node(name, focus: false)
141
90
  line = " #{id(name)}[\"#{Naming.words(name)}\"]"
142
91
  focus ? "#{line}:::focus" : line
143
92
  end
144
93
 
145
- # Renders one Mermaid edge declaration.
146
- #
147
- # @param from [String, Symbol] the source node's construct name
148
- # @param attribute [Bluebook::Attribute] the attribute the edge is labelled after
149
- # @param to [String, Symbol] the target node's construct name
150
- # @return [String] a Mermaid edge declaration line, labelled with the
151
- # attribute's spoken name
94
+ # Renders one Mermaid edge, labelled with the attribute's spoken name.
152
95
  def edge(from, attribute, to)
153
96
  " #{id(from)} -->|\"#{Naming.words(attribute.name).downcase}\"| #{id(to)}"
154
97
  end
@@ -3,38 +3,17 @@ require_relative "../../naming"
3
3
  module Hecks
4
4
  module Projections
5
5
  module Glossary
6
- # **The sensitive fields a glossary flags** — read from the markings a
7
- # deployment declares apart from the domain (`Privacy::Marking`, or a
8
- # `has_phi(readable_by:)` chain in a `.hecksagon`) and handed in as
9
- # `options[:markings]`. A marking names an aggregate by its qualified
10
- # name (`"Site::Registration"`) and a field by its dotted path
11
- # (`"attendee.medications"`). Its category is spoken as the acronym it
12
- # is, uppercased and never reworded, because the category vocabulary is
13
- # the deployment's own and open-ended.
6
+ # The sensitive fields a glossary flags, read from markings handed in as
7
+ # `options[:markings]` and keyed by aggregate name and dotted field path.
14
8
  module Sensitivity
15
9
  module_function
16
10
 
17
- # The markings that name one aggregate of the chapter.
18
- #
19
- # @param markings [Array<Hash{Symbol => String}>] every marking handed in, each
20
- # with `:domain`, `:attribute_path`, `:category` and `:readable_by`
21
- # @param chapter_name [String] the chapter's declared name
22
- # @param aggregate [Bluebook::Aggregate] the aggregate to find markings for
23
- # @return [Array<Hash{Symbol => String}>] the markings whose `:domain` is
24
- # `aggregate`'s qualified name, in the order they were declared
25
11
  def for_aggregate(markings, chapter_name, aggregate)
26
12
  qualified = "#{chapter_name}::#{aggregate.hecks_name}"
27
13
  markings.select { |marking| marking[:domain].to_s == qualified }
28
14
  end
29
15
 
30
- # The marked fields inside one value object, reached through whichever of
31
- # the aggregate's attributes holds that value object.
32
- #
33
- # @param marked [Array<Hash{Symbol => String}>] the aggregate's own markings
34
- # @param aggregate [Bluebook::Aggregate] the aggregate holding the value object
35
- # @param value_object [Bluebook::ValueObject] the value object to look inside
36
- # @return [Hash{String => Hash{Symbol => String}}] each marked field's name,
37
- # mapped to its marking; empty when no marking reaches one of its fields
16
+ # Marked fields inside a value object, matched by attribute name then field.
38
17
  def for_value_object(marked, aggregate, value_object)
39
18
  holders = aggregate.attributes.select { |attribute| attribute.type.to_s == value_object.hecks_name }
40
19
  holder_names = holders.map { |attribute| attribute.name.to_s }
@@ -44,18 +23,10 @@ module Hecks
44
23
  end
45
24
  end
46
25
 
47
- # The short tag a marked field carries beside its type.
48
- #
49
- # @param marking [Hash{Symbol => String}] one marking
50
- # @return [String] the marking's category, uppercased
26
+ # Uppercased, never otherwise reworded — the category vocabulary is the deployment's own.
51
27
  def tag(marking) = marking[:category].to_s.upcase
52
28
 
53
- # One line of an aggregate's "Handled as sensitive" list: which field, what
54
- # kind of sensitive, and who may read it unredacted.
55
- #
56
- # @param marking [Hash{Symbol => String}] one marking
57
- # @return [String] the field's spoken path, its uppercased category, and the
58
- # role that reads it unredacted, as one sentence
29
+ # Renders one "Handled as sensitive" line: field, category, and who may read it unredacted.
59
30
  def sentence(marking)
60
31
  path = marking[:attribute_path].to_s.split(".").map { |part| Naming.words(part).downcase }.join(" ")
61
32
  reader = Naming.words(marking[:readable_by]).downcase