hecks 2.8.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 (404) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +4 -6
  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 +17 -98
  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 +5 -48
  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 +31 -141
  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 +14 -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 +25 -31
  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 +16 -69
  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 -194
  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 -111
  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 +53 -267
  109. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +43 -305
  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 +6 -21
  114. data/lib/hecks/bluebook/model_check.rb +100 -597
  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 +4 -23
  128. data/lib/hecks/cli/document.rb +3 -21
  129. data/lib/hecks/cli/ir.rb +3 -5
  130. data/lib/hecks/cli/mcp.rb +2 -3
  131. data/lib/hecks/cli/mcp_door.rb +19 -114
  132. data/lib/hecks/cli/model_check.rb +18 -85
  133. data/lib/hecks/cli/project_cli.rb +7 -40
  134. data/lib/hecks/cli/project_diagrams.rb +0 -7
  135. data/lib/hecks/cli/run.rb +12 -58
  136. data/lib/hecks/cli/smoke_test.rb +2 -16
  137. data/lib/hecks/cli/stores.rb +1 -2
  138. data/lib/hecks/cli.rb +18 -24
  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 +82 -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 +9 -90
  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 +61 -64
  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 +6 -25
  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 +18 -124
  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 +150 -678
  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 +2 -15
  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 +42 -134
  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 +3 -6
  336. data/lib/hecks/release/runner/commands.rb +2 -4
  337. data/lib/hecks/release/runner/gem_publisher.rb +2 -3
  338. data/lib/hecks/release/runner/npm_publisher.rb +6 -20
  339. data/lib/hecks/release/runner/preflight.rb +4 -19
  340. data/lib/hecks/release/runner/tagger.rb +2 -9
  341. data/lib/hecks/release/runner.rb +3 -32
  342. data/lib/hecks/rendering.rb +4 -26
  343. data/lib/hecks/router/namespace_installer.rb +12 -36
  344. data/lib/hecks/router.rb +4 -8
  345. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  346. data/lib/hecks/runtime/boot_gates.rb +3 -18
  347. data/lib/hecks/runtime/caller.rb +19 -59
  348. data/lib/hecks/runtime/capability_graph.rb +5 -21
  349. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  350. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
  351. data/lib/hecks/runtime/command_interpreter.rb +124 -306
  352. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  353. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  354. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  355. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  356. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  357. data/lib/hecks/runtime/dependency_planning.rb +30 -102
  358. data/lib/hecks/runtime/dispatcher.rb +82 -241
  359. data/lib/hecks/runtime/entity_element.rb +40 -462
  360. data/lib/hecks/runtime/entity_interpreter.rb +64 -219
  361. data/lib/hecks/runtime/errors.rb +32 -115
  362. data/lib/hecks/runtime/event.rb +3 -25
  363. data/lib/hecks/runtime/identity.rb +18 -154
  364. data/lib/hecks/runtime/instance.rb +18 -150
  365. data/lib/hecks/runtime/interpreting.rb +11 -70
  366. data/lib/hecks/runtime/invocation.rb +28 -164
  367. data/lib/hecks/runtime/loader.rb +48 -186
  368. data/lib/hecks/runtime/outbox.rb +38 -261
  369. data/lib/hecks/runtime/policy_interpreter.rb +38 -200
  370. data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
  371. data/lib/hecks/runtime/query_interpreter.rb +45 -187
  372. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  373. data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
  374. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  375. data/lib/hecks/runtime/reference_hop.rb +8 -81
  376. data/lib/hecks/runtime/refusal_wording.rb +8 -89
  377. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  378. data/lib/hecks/runtime/registry/verification.rb +52 -225
  379. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  380. data/lib/hecks/runtime/registry.rb +99 -244
  381. data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
  382. data/lib/hecks/runtime/routing.rb +4 -15
  383. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  384. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  385. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  386. data/lib/hecks/runtime/tenant_check.rb +6 -68
  387. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  388. data/lib/hecks/runtime/value/admission.rb +16 -67
  389. data/lib/hecks/runtime/value/coercion.rb +155 -641
  390. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  391. data/lib/hecks/runtime/value.rb +12 -84
  392. data/lib/hecks/runtime.rb +17 -65
  393. data/lib/hecks/storehouse.rb +141 -568
  394. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
  395. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  396. data/lib/hecks/vendoring/git_environment.rb +2 -8
  397. data/lib/hecks/vendoring/git_source.rb +4 -10
  398. data/lib/hecks/vendoring.rb +7 -46
  399. data/lib/hecks/version.rb +3 -14
  400. data/lib/hecks.rb +26 -81
  401. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  402. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  403. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  404. metadata +3 -2
@@ -7,33 +7,17 @@ module Hecks
7
7
  # command-line launcher beside each domain, named after its bluebook, so
8
8
  # `Hecks.bluebook "QualityControl"` in `qa/` becomes `qa/quality_control`.
9
9
  #
10
- # ## A launcher, not a CLI
11
- #
12
- # Each file is a dozen lines pinning one directory and handing over to
13
- # `Facade::CliRunner`. The surface still comes from `Projector.call(:cli, …)` at
14
- # the moment it runs, so editing a chapter changes the launcher's behaviour
15
- # without regenerating anything. Re-run this when a domain is added or renamed.
16
- #
17
- # ## Beside the domain
18
- #
19
- # A domain's command line lives with the domain, so a folder is the whole unit.
20
- # The launcher boots `__dir__`, and reaches `lib` by counting how deep the domain
21
- # sits below the root, so no line knows where the checkout was cloned.
10
+ # Each launcher is a dozen lines pinning one directory and handing over to
11
+ # `Facade::CliRunner`; the surface itself is projected at the moment it runs,
12
+ # so editing a chapter changes behaviour without regenerating anything.
22
13
  module ProjectCli
23
14
  # Build output and other trees under a root that hold no domain a caller means.
24
15
  IGNORED = %r{\A(rust|deploy|tmp|coverage)/}
25
16
 
26
17
  module_function
27
18
 
28
- # Writes a launcher for each domain `argv` names, or for every domain under
29
- # `root`.
30
- #
31
- # @param argv [Array<String>] domain paths relative to `root`; empty for all of them
32
- # @param program [String] the name the generated header credits
33
- # @param root [String] the directory domains are found under and paths resolve against
34
- # @param remove_stale_bin [Boolean] whether to delete `root/bin/<name>`, where a
35
- # launcher for the same chapter would otherwise linger as a second front door
36
- # @return [void]
19
+ # `remove_stale_bin` deletes `root/bin/<name>`, where a launcher for the same
20
+ # chapter would otherwise linger as a second front door.
37
21
  def call(argv, program:, root:, remove_stale_bin: true)
38
22
  wanted = argv.empty? ? domains(root) : argv.map { |path| path.delete_prefix("#{root}/").chomp("/") }
39
23
 
@@ -50,11 +34,6 @@ module Hecks
50
34
  end
51
35
  end
52
36
 
53
- # Finds every domain under `root` a launcher can be written for.
54
- #
55
- # @param root [String] the directory to search under
56
- # @return [Array<String>] domain directory paths relative to `root`,
57
- # deduplicated and sorted
58
37
  def domains(root)
59
38
  folder = Adapters::Folder.new
60
39
  Dir.glob(File.join(root, "**/*.hecksagon"))
@@ -65,14 +44,8 @@ module Hecks
65
44
  .uniq.sort
66
45
  end
67
46
 
68
- # Boots the domain to read its declared name, which comes from
69
- # `Hecks.bluebook "…"` rather than the directory, so a domain renamed with
70
- # `formerly_known_as` gets a launcher under its new name.
71
- #
72
- # @param root [String] the directory `path` is relative to
73
- # @param path [String] a domain directory path
74
- # @return [String, nil] the domain's declared bluebook name, or nil after warning
75
- # when it fails to boot
47
+ # Reads the name from `Hecks.bluebook "…"` rather than the directory, so a
48
+ # domain using `formerly_known_as` gets a launcher under its current name.
76
49
  def bluebook_name(root, path)
77
50
  Hecks.boot(File.join(root, path), install_facade: false).registry.bluebooks.keys.first
78
51
  rescue StandardError => e
@@ -80,12 +53,6 @@ module Hecks
80
53
  nil
81
54
  end
82
55
 
83
- # Renders one domain's launcher.
84
- #
85
- # @param path [String] the domain directory path, relative to the root
86
- # @param name [String] the domain's declared bluebook name
87
- # @param program [String] the name the generated header credits
88
- # @return [String] the launcher script's full source
89
56
  def launcher(path, name, program)
90
57
  snake = Naming.snake(name)
91
58
  up = "../" * path.count("/").succ
@@ -9,13 +9,6 @@ module Hecks
9
9
  module ProjectDiagrams
10
10
  module_function
11
11
 
12
- # Projects and writes one chapter's diagrams, then lists what was written.
13
- #
14
- # @param argv [Array<String>] the domain path, then the chapter name
15
- # @param program [String] the name the usage message calls this command by
16
- # @param root [String] the directory `docs/generated/diagrams/` is written under
17
- # @return [void]
18
- # @raise [SystemExit] when either argument is missing
19
12
  def call(argv, program:, root:)
20
13
  usage = "usage: #{program} <domain-path> <ChapterName>"
21
14
  domain_path = argv[0] or abort usage
data/lib/hecks/cli/run.rb CHANGED
@@ -10,20 +10,12 @@ module Hecks
10
10
  # command line, or executes a JSON step list and reports instances, events,
11
11
  # refusals, reactions, sagas and query rows.
12
12
  #
13
- # ## Two forms, one argument
14
- #
15
- # `run bug.discover reference=BUG#1 severity=high …` needs no JSON. The verb
16
- # tree, every argument, its declared type and every way the verb can refuse are
17
- # projected out of the bluebook (`Projector::CliProjector`) and run by
18
- # `Facade::CliRunner`, so this knows nothing about any domain and its help
19
- # cannot go stale. The step-list form takes a script path, `-` for stdin, or the
20
- # JSON itself, which is how the corpus scripts under `spec/corpus/` are run.
21
- #
22
- # ## Standing in a domain is enough
23
- #
24
- # `Adapters::Folder#domain_root` walks up for the nearest `.hecksagon`, so inside
25
- # a domain the path can be left off. The first argument is a domain only when it
26
- # is a directory.
13
+ # `run bug.discover reference=BUG#1 severity=high …` needs no JSON; the verb
14
+ # tree and its arguments are projected from the bluebook, so this knows nothing
15
+ # about any domain and its help cannot go stale. The step-list form takes a
16
+ # script path, `-` for stdin, or the JSON itself. The first argument is a
17
+ # domain only when it is a directory; otherwise the nearest enclosing one is
18
+ # used.
27
19
  module Run
28
20
  module_function
29
21
 
@@ -59,19 +51,9 @@ module Hecks
59
51
  abort unmet.join("\n") unless unmet.empty?
60
52
  end
61
53
 
62
- # Boots `domain` and dispatches `argv` as a projected verb invocation, printing
63
- # the result and exiting the process.
64
- #
65
- # **No fall-through**. This is reached only when the argument is not
66
- # script-shaped, so a near miss deserves the runner's "did you mean" rather
67
- # than the step-list form's "no such script".
68
- #
69
- # @param domain [String] the domain's directory path
70
- # @param argv [Array<String>] the arguments after the domain, e.g.
71
- # `["bug.discover", "reference=BUG#1"]`
72
- # @param program [String] the name the runner's help calls this command by
73
- # @return [void]
74
- # @raise [SystemExit] always
54
+ # No fall-through: reached only when the argument is not script-shaped, so a
55
+ # near miss deserves the runner's "did you mean" rather than the step-list
56
+ # form's "no such script".
75
57
  def cli_form(domain, argv, program)
76
58
  runtime = Hecks.boot(domain, install_facade: false)
77
59
  text, status = Facade::CliRunner.call(runtime: runtime, argv: argv, program: program)
@@ -79,20 +61,10 @@ module Hecks
79
61
  exit 0
80
62
  end
81
63
 
82
- # Says whether `arg` is a step list rather than a verb: stdin, inline JSON, or
83
- # a file that exists.
84
- #
85
- # @param arg [String] the first argument after the domain
86
- # @return [Boolean] true when `arg` is script-shaped
87
64
  def script_shaped?(arg) = arg == "-" || arg.match?(/\A\s*\{/) || File.file?(arg)
88
65
 
89
- # Reads the step list from stdin, from the argument itself, or from a file,
90
- # decided by looking, because a script beginning with `{` is not a filename
66
+ # Decided by looking, because a script beginning with `{` is not a filename
91
67
  # anybody meant.
92
- #
93
- # @param script [String] `-`, inline JSON, or a file path
94
- # @return [String] the script's JSON text
95
- # @raise [SystemExit] when `script` names no file
96
68
  def read_source(script)
97
69
  case script
98
70
  when "-" then $stdin.read
@@ -102,25 +74,14 @@ module Hecks
102
74
  end
103
75
  end
104
76
 
105
- # Parses the step list before anything boots, because booting opens a real
106
- # store and a typo in the JSON should cost a sentence, not a connection.
107
- #
108
- # @param source [String] the script's JSON text
109
- # @return [Hash{String => Object}] the parsed script
110
- # @raise [SystemExit] when `source` is not JSON
77
+ # Parsed before anything boots, because booting opens a real store and a typo
78
+ # in the JSON should cost a sentence, not a connection.
111
79
  def parse(source)
112
80
  JSON.parse(source)
113
81
  rescue JSON::ParserError => e
114
82
  abort "that is not JSON: #{e.message.lines.first.strip}"
115
83
  end
116
84
 
117
- # Runs every step and gathers what the runtime holds afterwards.
118
- #
119
- # @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted domain
120
- # @param steps [Array<Hash{String => Object}>] the script's steps, each a
121
- # `"verb"` or a `"query"` with optional `"args"`
122
- # @return [Hash{Symbol => Object}] `:instances`, `:events`, `:refusals`,
123
- # `:reactions`, `:sagas` and `:queries`, in the order they are printed
124
85
  def execute(runtime, steps)
125
86
  refusals = []
126
87
  queries = []
@@ -171,13 +132,6 @@ module Hecks
171
132
  end
172
133
  end
173
134
 
174
- # Checks the script's `"expectations"` against what the run produced.
175
- #
176
- # @param expectations [Hash{String => Object}] the script's `"event_names"`,
177
- # `"refusals"` and `"instances"` expectations; `{}` when it declares none
178
- # @param report [Hash{Symbol => Object}] what `execute` answered
179
- # @return [Array<String>] one message per unmet expectation; empty when every
180
- # one held
181
135
  def unmet_expectations(expectations, report)
182
136
  missing_events = Array(expectations["event_names"]) - report[:events].map { |event| event[:name] }
183
137
  unmet = []
@@ -7,22 +7,12 @@ module Hecks
7
7
  # and dispatches one synthesized call per declared command and report
8
8
  # (`Bluebook::SmokeTest`), printing every failure rather than the first.
9
9
  #
10
- # It needs a real `.hecksagon`: a bare `.bluebook` with nothing bound to an
11
- # adapter has nothing to run commands against. A failure may be a domain bug or
12
- # a value the synthesizer's naive choices (0, an empty list, "smoke-test") cannot
13
- # satisfy; the message underneath says which. Smoke-testing proves nothing
10
+ # Needs a real `.hecksagon`; a failure may be a domain bug or a value the
11
+ # synthesizer's naive choices cannot satisfy — smoke-testing proves nothing
14
12
  # crashes, not that an answer is right.
15
13
  module SmokeTest
16
14
  module_function
17
15
 
18
- # Smoke-tests the domain `argv` names, or every wired domain under
19
- # `root/examples/`, and exits with the verdict.
20
- #
21
- # @param argv [Array<String>] an optional domain directory
22
- # @param root [String] the directory whose `examples/*` are tested when `argv`
23
- # names no domain
24
- # @return [void]
25
- # @raise [SystemExit] always: 0 when clean, 1 with failures or no domain found
26
16
  def call(argv, root:)
27
17
  dir_arg = argv.first
28
18
  targets = dir_arg ? [dir_arg] : Dir.glob("#{root}/examples/*/").map { |d| d.chomp("/") }.select { |d| wired?(d) }
@@ -35,10 +25,6 @@ module Hecks
35
25
  exit(ok ? 0 : 1)
36
26
  end
37
27
 
38
- # Says whether `dir`, or something nested under it, is a bindable domain.
39
- #
40
- # @param dir [String] a directory to check
41
- # @return [Boolean] true if `dir` contains at least one `.hecksagon` file
42
28
  def wired?(dir) = !Dir.glob(File.join(dir, "**/*.hecksagon")).empty?
43
29
 
44
30
  # @api private
@@ -4,8 +4,7 @@ require_relative "../../hecks"
4
4
  module Hecks
5
5
  module CLI
6
6
  # The command behind `bin/stores` and `hecks stores`: every aggregate's current
7
- # records as JSON, the head rather than the journal (`bin/history` prints the
8
- # full write history).
7
+ # records as JSON (the head, not the journal — see `bin/history` for that).
9
8
  module Stores
10
9
  module_function
11
10
 
data/lib/hecks/cli.rb CHANGED
@@ -1,27 +1,9 @@
1
1
  module Hecks
2
2
  # The `hecks` command an installed gem puts on the path: one router over the
3
- # domain-operator tools, each of which also runs from a checkout as `bin/<name>`.
3
+ # domain-operator tools, each also runnable from a checkout as `bin/<name>`.
4
4
  #
5
- # ## A router, not a second copy
6
- #
7
- # Every subcommand's logic lives in `lib/hecks/cli/`, and the matching `bin/`
8
- # script is a thin wrapper over the same entry point, so `hecks run` and
9
- # `bin/run` cannot drift apart. The domain-scoped verbs go through
10
- # `Facade::CliRunner`, the same way `bin/run` does.
11
- #
12
- # ## What a checkout has and an install does not
13
- #
14
- # The `bin/` wrappers pass the repository root, which is where they look for
15
- # `examples/`, `rust/` and `docs/generated/`. Here the root is the working
16
- # directory, so a command that lists or writes files does it where the caller
17
- # stands. `model_check` with no domain sweeps the repository's corpus, which an
18
- # install does not carry, so here it needs at least one domain path.
19
- #
20
- # ## Loading
21
- #
22
- # Nothing here requires the framework. A subcommand loads it when it runs, and
23
- # `mcp` checks its transport before anything else loads, as
24
- # `McpStdioGuard.enforce_stdio!` requires.
5
+ # Every subcommand's logic lives under `cli/`, with `bin/<name>` a thin wrapper
6
+ # over the same entry point, so the two can't drift apart.
25
7
  #
26
8
  # See `docs/decisions/0066-the-gem-ships-a-hecks-executable-and-dev-tooling-stays-in-the-repo.md`.
27
9
  module CLI
@@ -74,6 +56,18 @@ module Hecks
74
56
 
75
57
  HELP_FLAGS = ["--help", "-h"].freeze
76
58
 
59
+ # Printed above the usage line by `overview`, on every path that reaches it
60
+ # (a bare `hecks`, `hecks --help`, and an unknown subcommand alike).
61
+ HERO = <<~BANNER.freeze
62
+ # # ##### #### # # ####
63
+ # # # # # # #
64
+ ##### #### # ## ###
65
+ # # # # # # #
66
+ # # ##### #### # # ####
67
+
68
+ It's all about the specs
69
+ BANNER
70
+
77
71
  # Exit status for a missing or unknown subcommand.
78
72
  USAGE_STATUS = 2
79
73
 
@@ -81,9 +75,8 @@ module Hecks
81
75
 
82
76
  # Routes `argv` to its subcommand and runs it.
83
77
  #
84
- # A subcommand followed by only `--help` or `-h` prints that subcommand's usage
85
- # without running it; any other arguments pass through untouched, so
86
- # `hecks run order.place --help` still reaches the verb's own help.
78
+ # A subcommand followed only by `--help`/`-h` prints its usage without
79
+ # running it; other arguments still reach the verb itself.
87
80
  #
88
81
  # @param argv [Array<String>] the command line, subcommand first
89
82
  # @param out [#puts] where help goes
@@ -148,6 +141,7 @@ module Hecks
148
141
 
149
142
  # @api private
150
143
  def overview(io)
144
+ io.puts HERO
151
145
  io.puts "usage: hecks <command> [arguments]"
152
146
  io.puts ""
153
147
  width = COMMANDS.keys.map(&:length).max
@@ -1,29 +1,12 @@
1
1
  module Hecks
2
- # The invisible field a built construct carries.
2
+ # The invisible identity a built construct carries: an owner chain under `hecks_`-prefixed
3
+ # fields, not an attribute and not a key in `to_h`.
3
4
  #
4
- # ## Identity
5
+ # The fully-qualified name walks owners and matches the id `MetaValidator::Judge#identify` mints.
5
6
  #
6
- # A construct is a record with an owner chain — the chapter (Bluebook)
7
- # owns its aggregates, an aggregate owns everything declared on it — and the
8
- # bluebook identity is carried in its own field, under a `hecks_` prefix that
9
- # no domain attribute can collide with. Invisible means exactly that: not an
10
- # attribute, not a key in `to_h`, not a reader on instances. Framework
11
- # metadata about the construct, not part of the domain it describes.
12
- #
13
- # The identity is computed by walking owners rather than stamped, so nothing
14
- # has to be re-stamped when a chapter is assembled after its aggregates:
15
- #
16
- # Pizzas the chapter — no owner
7
+ # Pizzas the chapter, no owner
17
8
  # Pizzas::Pizza an aggregate joins its chapter with ::
18
9
  # Pizzas::Pizza.Price everything else joins its owner with .
19
- #
20
- # That spelling is not invented here. It is the id `MetaValidator::Judge`
21
- # already mints in `#identify`, so a construct and the meta-domain's
22
- # record of that construct carry the same identity, and there is no
23
- # translation table between them to be quietly wrong in.
24
- #
25
- # ## Usage
26
- #
27
10
  # price = Class.new(ValueObject) # a declaration holder
28
11
  # price.hecks_name = "Price"
29
12
  # price.hecks_owner = pizza_ir # the Aggregate that declares it
@@ -32,15 +15,12 @@ module Hecks
32
15
  # A construct asked for an identity it cannot compute.
33
16
  class Unowned < StandardError; end
34
17
 
35
- # What declares this one — the chapter above an aggregate, the aggregate
36
- # above a value object. nil for a chapter, which is the top.
18
+ # What declares this construct; nil for a chapter, which is the top.
37
19
  attr_accessor :hecks_owner
38
20
 
39
21
  attr_writer :hecks_name
40
22
 
41
- # A chapter is the only construct that legitimately has no owner. Everything
42
- # else is declared in something, so a missing owner is an unstamped construct
43
- # rather than a top — see hecks_fqn.
23
+ # Marks a chapter, the only construct that legitimately has no owner.
44
24
  attr_writer :hecks_root
45
25
 
46
26
  # Whether this construct is the top of its own owner chain.
@@ -53,18 +33,12 @@ module Hecks
53
33
  # @return [String] the construct's own name, without any owner prefix
54
34
  def hecks_name = @hecks_name
55
35
 
56
- # How this construct joins its owner. An aggregate is a member of its
57
- # chapter's namespace (`::`) ; everything else is declared on its owner
58
- # (`.`). Overridden by Aggregate, defaulted here for every other construct.
36
+ # How this construct joins its owner: `::` for an aggregate, `.` for everything else.
59
37
  #
60
38
  # @return [String] `"."`, the separator this construct uses in `hecks_fqn`
61
39
  def hecks_separator = "."
62
40
 
63
- # Refuses rather than guesses. A construct with no owner and no claim to be a
64
- # chapter has simply not been stamped yet — entity commands are in that state
65
- # while entities are still IR objects — and answering the bare name would be a
66
- # plausible half-truth that no test would notice. That shape of falsehood is
67
- # what this repo keeps finding, so it goes red instead.
41
+ # Refuses rather than answering a bare name for an unstamped construct.
68
42
  #
69
43
  # @return [String] the fully-qualified name, joining every owner from the
70
44
  # chapter down to this construct