hecks 0.2.0 → 0.3.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 (408) hide show
  1. checksums.yaml +5 -5
  2. data/lib/hecks/adapters/driven/claude_code.adapter +3 -0
  3. data/lib/hecks/adapters/driven/claude_code.rb +127 -0
  4. data/lib/hecks/adapters/driven/d1.adapter +12 -0
  5. data/lib/hecks/adapters/driven/d1.rb +403 -0
  6. data/lib/hecks/adapters/driven/folder.adapter +3 -0
  7. data/lib/hecks/adapters/driven/folder.rb +199 -0
  8. data/lib/hecks/adapters/driven/google_authentication.adapter +3 -0
  9. data/lib/hecks/adapters/driven/google_authentication.rb +100 -0
  10. data/lib/hecks/adapters/driven/governance_authorization.adapter +3 -0
  11. data/lib/hecks/adapters/driven/governance_authorization.rb +62 -0
  12. data/lib/hecks/adapters/driven/heki/journal.rb +51 -0
  13. data/lib/hecks/adapters/driven/heki/saga_store.rb +0 -0
  14. data/lib/hecks/adapters/driven/heki/snapshot.rb +38 -0
  15. data/lib/hecks/adapters/driven/heki.adapter +4 -0
  16. data/lib/hecks/adapters/driven/heki.rb +148 -0
  17. data/lib/hecks/adapters/driven/identity_registry.adapter +3 -0
  18. data/lib/hecks/adapters/driven/identity_registry.rb +26 -0
  19. data/lib/hecks/adapters/driven/in_memory_ordering.rb +51 -0
  20. data/lib/hecks/adapters/driven/lambda/client.rb +63 -0
  21. data/lib/hecks/adapters/driven/lambda.adapter +4 -0
  22. data/lib/hecks/adapters/driven/lambda.rb +131 -0
  23. data/lib/hecks/adapters/driven/memory.adapter +3 -0
  24. data/lib/hecks/adapters/driven/memory.rb +103 -0
  25. data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +3 -0
  26. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +28 -0
  27. data/lib/hecks/adapters/driven/postgres/codec.rb +80 -0
  28. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +168 -0
  29. data/lib/hecks/adapters/driven/postgres.adapter +5 -0
  30. data/lib/hecks/adapters/driven/postgres.rb +391 -0
  31. data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +171 -0
  32. data/lib/hecks/adapters/driven/postgres_era/lineage/field_cache.rb +190 -0
  33. data/lib/hecks/adapters/driven/postgres_era/lineage/head_compiler.rb +429 -0
  34. data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +166 -0
  35. data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +286 -0
  36. data/lib/hecks/adapters/driven/postgres_era/lineage/resumable_backfill.rb +168 -0
  37. data/lib/hecks/adapters/driven/postgres_era/lineage/tail_merge.rb +163 -0
  38. data/lib/hecks/adapters/driven/postgres_era/lineage/transform_installer.rb +114 -0
  39. data/lib/hecks/adapters/driven/postgres_era/lineage.rb +137 -0
  40. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +89 -0
  41. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +82 -0
  42. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +43 -0
  43. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +132 -0
  44. data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +74 -0
  45. data/lib/hecks/adapters/driven/postgres_era.adapter +6 -0
  46. data/lib/hecks/adapters/driven/postgres_era.rb +671 -0
  47. data/lib/hecks/adapters/driven/prism.adapter +3 -0
  48. data/lib/hecks/adapters/driven/prism.rb +80 -0
  49. data/lib/hecks/adapters/driven/secure_random_identity.adapter +3 -0
  50. data/lib/hecks/adapters/driven/secure_random_identity.rb +14 -0
  51. data/lib/hecks/adapters/driven/sql_query_builder.rb +221 -0
  52. data/lib/hecks/adapters/driven/sqlite/codec.rb +63 -0
  53. data/lib/hecks/adapters/driven/sqlite/projection.rb +105 -0
  54. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +180 -0
  55. data/lib/hecks/adapters/driven/sqlite.adapter +9 -0
  56. data/lib/hecks/adapters/driven/sqlite.rb +285 -0
  57. data/lib/hecks/adapters/driven/system_clock.adapter +3 -0
  58. data/lib/hecks/adapters/driven/system_clock.rb +14 -0
  59. data/lib/hecks/adapters/driven.rb +36 -0
  60. data/lib/hecks/adapters.rb +6 -0
  61. data/lib/hecks/behaviors/dsl.rb +96 -0
  62. data/lib/hecks/behaviors/expectations.rb +280 -0
  63. data/lib/hecks/behaviors/ir.rb +31 -0
  64. data/lib/hecks/behaviors/rspec.rb +42 -0
  65. data/lib/hecks/behaviors/runner.rb +96 -0
  66. data/lib/hecks/behaviors.rb +25 -0
  67. data/lib/hecks/bluebook/aggregate.rb +108 -0
  68. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +134 -0
  69. data/lib/hecks/bluebook/assembly/build.rb +48 -0
  70. data/lib/hecks/bluebook/assembly/contract.rb +112 -0
  71. data/lib/hecks/bluebook/assembly/contracts.rb +409 -0
  72. data/lib/hecks/bluebook/assembly/marks.rb +227 -0
  73. data/lib/hecks/bluebook/assembly/specializer.rb +70 -0
  74. data/lib/hecks/bluebook/assembly.rb +78 -0
  75. data/lib/hecks/bluebook/attribute.rb +96 -0
  76. data/lib/hecks/bluebook/behaviour/aggregate.rb +83 -0
  77. data/lib/hecks/bluebook/behaviour/attribute.rb +27 -0
  78. data/lib/hecks/bluebook/behaviour/chapter.rb +72 -0
  79. data/lib/hecks/bluebook/behaviour/command.rb +116 -0
  80. data/lib/hecks/bluebook/behaviour/domain_port.rb +25 -0
  81. data/lib/hecks/bluebook/behaviour/entity.rb +59 -0
  82. data/lib/hecks/bluebook/behaviour/hexagon.rb +50 -0
  83. data/lib/hecks/bluebook/behaviour/lifecycle.rb +51 -0
  84. data/lib/hecks/bluebook/behaviour/policy.rb +52 -0
  85. data/lib/hecks/bluebook/behaviour/process_manager.rb +38 -0
  86. data/lib/hecks/bluebook/behaviour/query.rb +10 -0
  87. data/lib/hecks/bluebook/behaviour/read_model.rb +29 -0
  88. data/lib/hecks/bluebook/behaviour/traits.rb +81 -0
  89. data/lib/hecks/bluebook/behaviour/value_object.rb +33 -0
  90. data/lib/hecks/bluebook/chapter.rb +68 -0
  91. data/lib/hecks/bluebook/command.rb +124 -0
  92. data/lib/hecks/bluebook/domain_port.rb +102 -0
  93. data/lib/hecks/bluebook/dsl/adapter_builder.rb +34 -0
  94. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +906 -0
  95. data/lib/hecks/bluebook/dsl/attribute_collector.rb +327 -0
  96. data/lib/hecks/bluebook/dsl/binding_proxy.rb +71 -0
  97. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +1018 -0
  98. data/lib/hecks/bluebook/dsl/command_builder.rb +626 -0
  99. data/lib/hecks/bluebook/dsl/const_shim.rb +81 -0
  100. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +79 -0
  101. data/lib/hecks/bluebook/dsl/entity_builder.rb +305 -0
  102. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +366 -0
  103. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +163 -0
  104. data/lib/hecks/bluebook/dsl/identity_declaration.rb +191 -0
  105. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +44 -0
  106. data/lib/hecks/bluebook/dsl/malformed.rb +7 -0
  107. data/lib/hecks/bluebook/dsl/policy_builder.rb +120 -0
  108. data/lib/hecks/bluebook/dsl/port_builder.rb +30 -0
  109. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +142 -0
  110. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +207 -0
  111. data/lib/hecks/bluebook/dsl/query_builder.rb +113 -0
  112. data/lib/hecks/bluebook/dsl/read_model_builder.rb +233 -0
  113. data/lib/hecks/bluebook/dsl/rule_reference.rb +172 -0
  114. data/lib/hecks/bluebook/dsl/translation_builder.rb +243 -0
  115. data/lib/hecks/bluebook/dsl/value_object_builder.rb +178 -0
  116. data/lib/hecks/bluebook/dsl/word_gate.rb +221 -0
  117. data/lib/hecks/bluebook/dsl/world_builder.rb +77 -0
  118. data/lib/hecks/bluebook/dsl.rb +45 -0
  119. data/lib/hecks/bluebook/entity.rb +103 -0
  120. data/lib/hecks/bluebook/expression/canonical_form.rb +55 -0
  121. data/lib/hecks/bluebook/expression/evaluator.rb +261 -0
  122. data/lib/hecks/bluebook/expression/projection.json +170 -0
  123. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +233 -0
  124. data/lib/hecks/bluebook/expression/resolver.rb +630 -0
  125. data/lib/hecks/bluebook/expression.rb +13 -0
  126. data/lib/hecks/bluebook/hexagon.rb +60 -0
  127. data/lib/hecks/bluebook/lifecycle.rb +42 -0
  128. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +54 -0
  129. data/lib/hecks/bluebook/meta_validator/judge.rb +559 -0
  130. data/lib/hecks/bluebook/meta_validator/plan.rb +332 -0
  131. data/lib/hecks/bluebook/meta_validator/port_judge.rb +47 -0
  132. data/lib/hecks/bluebook/meta_validator/readings.rb +350 -0
  133. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +312 -0
  134. data/lib/hecks/bluebook/meta_validator/shapes.rb +246 -0
  135. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +255 -0
  136. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +138 -0
  137. data/lib/hecks/bluebook/meta_validator/world_judge.rb +78 -0
  138. data/lib/hecks/bluebook/meta_validator.rb +452 -0
  139. data/lib/hecks/bluebook/model_check.rb +318 -0
  140. data/lib/hecks/bluebook/pattern_subset.rb +120 -0
  141. data/lib/hecks/bluebook/policy.rb +41 -0
  142. data/lib/hecks/bluebook/process_manager.rb +86 -0
  143. data/lib/hecks/bluebook/project_discovery.rb +30 -0
  144. data/lib/hecks/bluebook/project_loader.rb +40 -0
  145. data/lib/hecks/bluebook/project_register.rb +82 -0
  146. data/lib/hecks/bluebook/query.rb +61 -0
  147. data/lib/hecks/bluebook/read_model.rb +109 -0
  148. data/lib/hecks/bluebook/reference.rb +74 -0
  149. data/lib/hecks/bluebook/smoke_test.rb +166 -0
  150. data/lib/hecks/bluebook/synthesizer.rb +95 -0
  151. data/lib/hecks/bluebook/translation.rb +92 -0
  152. data/lib/hecks/bluebook/value_object.rb +58 -0
  153. data/lib/hecks/bluebook.rb +74 -0
  154. data/lib/hecks/codemod.rb +342 -0
  155. data/lib/hecks/construct.rb +71 -0
  156. data/lib/hecks/deploy/bluebook/deploy.bluebook +219 -0
  157. data/lib/hecks/deploy/bluebook/deploy.hecksagon +4 -0
  158. data/lib/hecks/deploy/oidc.json +18 -0
  159. data/lib/hecks/doc/reference.rb +389 -0
  160. data/lib/hecks/embryonaut_bluebook.rb +75 -0
  161. data/lib/hecks/facade/cli_door.rb +116 -0
  162. data/lib/hecks/facade/cli_runner.rb +190 -0
  163. data/lib/hecks/facade/command_request.rb +105 -0
  164. data/lib/hecks/facade/handle.rb +173 -0
  165. data/lib/hecks/facade/json_door.rb +154 -0
  166. data/lib/hecks/facade/surface/aggregate_door.rb +185 -0
  167. data/lib/hecks/facade/surface/chapter.rb +107 -0
  168. data/lib/hecks/facade/surface.rb +48 -0
  169. data/lib/hecks/facade.rb +44 -0
  170. data/lib/hecks/forms/app.rb +300 -0
  171. data/lib/hecks/forms/command_form_renderer.rb +113 -0
  172. data/lib/hecks/forms/examples/banking_console.bluebook +3 -0
  173. data/lib/hecks/forms/field_renderer.rb +170 -0
  174. data/lib/hecks/forms/field_shape.rb +232 -0
  175. data/lib/hecks/forms/html.rb +53 -0
  176. data/lib/hecks/forms/index_renderer.rb +35 -0
  177. data/lib/hecks/forms/page.rb +157 -0
  178. data/lib/hecks/forms/params.rb +132 -0
  179. data/lib/hecks/forms/query_form_renderer.rb +114 -0
  180. data/lib/hecks/forms/record_renderer.rb +115 -0
  181. data/lib/hecks/forms/record_table.rb +63 -0
  182. data/lib/hecks/forms/reference_options.rb +30 -0
  183. data/lib/hecks/forms/value_object_shape.rb +46 -0
  184. data/lib/hecks/forms.rb +54 -0
  185. data/lib/hecks/fqn.rb +94 -0
  186. data/lib/hecks/framework/bluebook/compliance.bluebook +1 -0
  187. data/lib/hecks/framework/bluebook/console_settings.bluebook +489 -0
  188. data/lib/hecks/framework/bluebook/framework.hecksagon +32 -0
  189. data/lib/hecks/framework/bluebook/governance.bluebook +130 -0
  190. data/lib/hecks/framework/bluebook/identity.bluebook +90 -0
  191. data/lib/hecks/framework/oidc.json +39 -0
  192. data/lib/hecks/framework.rb +90 -0
  193. data/lib/hecks/freezer.rb +67 -0
  194. data/lib/hecks/fuzzing/invalid_value_generator.rb +86 -0
  195. data/lib/hecks/fuzzing/isolated_boot.rb +92 -0
  196. data/lib/hecks/fuzzing/properties.rb +1146 -0
  197. data/lib/hecks/fuzzing/replay.rb +635 -0
  198. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +93 -0
  199. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +54 -0
  200. data/lib/hecks/fuzzing/sequence_generator/picker.rb +96 -0
  201. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +185 -0
  202. data/lib/hecks/fuzzing/sequence_generator.rb +130 -0
  203. data/lib/hecks/fuzzing/value_generator.rb +177 -0
  204. data/lib/hecks/fuzzing.rb +12 -0
  205. data/lib/hecks/grammar/evolve.rb +291 -0
  206. data/lib/hecks/grammar/expression.bluebook +417 -0
  207. data/lib/hecks/grammar/expression_operators.json +1152 -0
  208. data/lib/hecks/grammar/grammar.hecksagon +20 -0
  209. data/lib/hecks/grammar/oidc.json +69 -0
  210. data/lib/hecks/grammar/translation.bluebook +203 -0
  211. data/lib/hecks/grammar.rb +178 -0
  212. data/lib/hecks/ir.rb +126 -0
  213. data/lib/hecks/language/adapter.bluebook +116 -0
  214. data/lib/hecks/language/bluebook/aggregate.bluebook +581 -0
  215. data/lib/hecks/language/bluebook/attaches/paging.bluebook +76 -0
  216. data/lib/hecks/language/bluebook/bluebook.bluebook +256 -0
  217. data/lib/hecks/language/bluebook/bluebook.hecksagon +24 -0
  218. data/lib/hecks/language/bluebook/command.bluebook +437 -0
  219. data/lib/hecks/language/bluebook/entity.bluebook +316 -0
  220. data/lib/hecks/language/bluebook/policy.bluebook +172 -0
  221. data/lib/hecks/language/bluebook/process_manager.bluebook +264 -0
  222. data/lib/hecks/language/bluebook/projection.bluebook +267 -0
  223. data/lib/hecks/language/bluebook/query.bluebook +245 -0
  224. data/lib/hecks/language/bluebook/shape.bluebook +292 -0
  225. data/lib/hecks/language/bluebook/syntax.bluebook +447 -0
  226. data/lib/hecks/language/bluebook/vocabulary.bluebook +364 -0
  227. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +51 -0
  228. data/lib/hecks/language/hecksagon/domain_port.bluebook +76 -0
  229. data/lib/hecks/language/hecksagon/hecksagon.bluebook +131 -0
  230. data/lib/hecks/language/hecksagon/port_operation.bluebook +102 -0
  231. data/lib/hecks/language/oidc.json +313 -0
  232. data/lib/hecks/language/port.bluebook +92 -0
  233. data/lib/hecks/language/translation/translation.bluebook +110 -0
  234. data/lib/hecks/language/translation/translation_aggregate.bluebook +267 -0
  235. data/lib/hecks/language/world/wiring.bluebook +62 -0
  236. data/lib/hecks/language/world/world.bluebook +84 -0
  237. data/lib/hecks/literal.rb +125 -0
  238. data/lib/hecks/naming.rb +121 -0
  239. data/lib/hecks/ports/access_control.port +4 -0
  240. data/lib/hecks/ports/access_control.rb +62 -0
  241. data/lib/hecks/ports/agent/answers.rb +104 -0
  242. data/lib/hecks/ports/agent.port +4 -0
  243. data/lib/hecks/ports/agent.rb +167 -0
  244. data/lib/hecks/ports/authentication.port +4 -0
  245. data/lib/hecks/ports/authentication.rb +50 -0
  246. data/lib/hecks/ports/authorization.port +4 -0
  247. data/lib/hecks/ports/authorization.rb +59 -0
  248. data/lib/hecks/ports/clock.port +4 -0
  249. data/lib/hecks/ports/clock.rb +62 -0
  250. data/lib/hecks/ports/extraction.port +4 -0
  251. data/lib/hecks/ports/extraction.rb +37 -0
  252. data/lib/hecks/ports/identity_assignment.port +4 -0
  253. data/lib/hecks/ports/identity_assignment.rb +45 -0
  254. data/lib/hecks/ports/identity_generation.port +4 -0
  255. data/lib/hecks/ports/identity_generation.rb +49 -0
  256. data/lib/hecks/ports/identity_resolution.port +4 -0
  257. data/lib/hecks/ports/identity_resolution.rb +40 -0
  258. data/lib/hecks/ports/loading.port +4 -0
  259. data/lib/hecks/ports/loading.rb +13 -0
  260. data/lib/hecks/ports/persistence/append_only.rb +102 -0
  261. data/lib/hecks/ports/persistence/binding_policy.rb +56 -0
  262. data/lib/hecks/ports/persistence/execution.rb +18 -0
  263. data/lib/hecks/ports/persistence/lineage.rb +277 -0
  264. data/lib/hecks/ports/persistence/null_saga_store.rb +25 -0
  265. data/lib/hecks/ports/persistence/remote_runtime.rb +42 -0
  266. data/lib/hecks/ports/persistence/repository_factory.rb +30 -0
  267. data/lib/hecks/ports/persistence.port +4 -0
  268. data/lib/hecks/ports/persistence.rb +39 -0
  269. data/lib/hecks/ports/projection.port +4 -0
  270. data/lib/hecks/ports/projection.rb +76 -0
  271. data/lib/hecks/ports/query/in_memory.rb +60 -0
  272. data/lib/hecks/ports/query/ordering.rb +41 -0
  273. data/lib/hecks/ports/query.rb +36 -0
  274. data/lib/hecks/ports.rb +27 -0
  275. data/lib/hecks/projections/diagrams.rb +413 -0
  276. data/lib/hecks/projections/ir.rb +18 -0
  277. data/lib/hecks/projections/model/deviations.rb +98 -0
  278. data/lib/hecks/projections/model.rb +145 -0
  279. data/lib/hecks/projections/oidc.rb +110 -0
  280. data/lib/hecks/projections/parser_table.rb +159 -0
  281. data/lib/hecks/projections/reference.rb +38 -0
  282. data/lib/hecks/projections/shape.rb +31 -0
  283. data/lib/hecks/projections/statements.rb +110 -0
  284. data/lib/hecks/projections/vocabulary.rb +100 -0
  285. data/lib/hecks/projections.rb +32 -0
  286. data/lib/hecks/projector/cli_projector.rb +437 -0
  287. data/lib/hecks/projector/docs_projector.rb +321 -0
  288. data/lib/hecks/projector/exporter.rb +141 -0
  289. data/lib/hecks/projector/ir_projector.rb +18 -0
  290. data/lib/hecks/projector/narrate_projector.rb +243 -0
  291. data/lib/hecks/projector/target.rb +97 -0
  292. data/lib/hecks/projector.rb +186 -0
  293. data/lib/hecks/query_ir.rb +392 -0
  294. data/lib/hecks/query_specification/common/authorization_spec.rb +9 -0
  295. data/lib/hecks/query_specification/common/comparators.rb +25 -0
  296. data/lib/hecks/query_specification/common/comparison.rb +174 -0
  297. data/lib/hecks/query_specification/common/cursor_spec.rb +9 -0
  298. data/lib/hecks/query_specification/common/dsl.rb +58 -0
  299. data/lib/hecks/query_specification/common/inspection_spec.rb +9 -0
  300. data/lib/hecks/query_specification/common/limit_spec.rb +9 -0
  301. data/lib/hecks/query_specification/common/null_policy.rb +80 -0
  302. data/lib/hecks/query_specification/common/null_semantics.rb +11 -0
  303. data/lib/hecks/query_specification/common/offset_spec.rb +9 -0
  304. data/lib/hecks/query_specification/common/options.rb +32 -0
  305. data/lib/hecks/query_specification/common/order_by.rb +9 -0
  306. data/lib/hecks/query_specification/common/specification.rb +10 -0
  307. data/lib/hecks/query_specification/common/where_clause.rb +9 -0
  308. data/lib/hecks/query_specification/field_path.rb +89 -0
  309. data/lib/hecks/query_specification/hop_path.rb +130 -0
  310. data/lib/hecks/query_specification/read_model/specification.rb +18 -0
  311. data/lib/hecks/query_specification.rb +14 -0
  312. data/lib/hecks/rendering.rb +48 -0
  313. data/lib/hecks/router/namespace_installer.rb +157 -0
  314. data/lib/hecks/router.rb +70 -0
  315. data/lib/hecks/runtime/caller.rb +50 -0
  316. data/lib/hecks/runtime/capability_graph.rb +44 -0
  317. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +124 -0
  318. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +248 -0
  319. data/lib/hecks/runtime/command_interpreter.rb +413 -0
  320. data/lib/hecks/runtime/command_rules/admissibility.rb +307 -0
  321. data/lib/hecks/runtime/command_rules/arithmetic.rb +254 -0
  322. data/lib/hecks/runtime/command_rules/authorization.rb +64 -0
  323. data/lib/hecks/runtime/command_rules/emission.rb +34 -0
  324. data/lib/hecks/runtime/command_rules/references.rb +181 -0
  325. data/lib/hecks/runtime/command_rules.rb +28 -0
  326. data/lib/hecks/runtime/dependency_planning.rb +231 -0
  327. data/lib/hecks/runtime/dispatcher.rb +286 -0
  328. data/lib/hecks/runtime/entity_element.rb +253 -0
  329. data/lib/hecks/runtime/entity_interpreter.rb +228 -0
  330. data/lib/hecks/runtime/era_check.rb +136 -0
  331. data/lib/hecks/runtime/era_guard/shape_diff.rb +128 -0
  332. data/lib/hecks/runtime/era_guard.rb +193 -0
  333. data/lib/hecks/runtime/era_tamper.rb +61 -0
  334. data/lib/hecks/runtime/errors.rb +100 -0
  335. data/lib/hecks/runtime/event.rb +51 -0
  336. data/lib/hecks/runtime/identity.rb +128 -0
  337. data/lib/hecks/runtime/instance.rb +120 -0
  338. data/lib/hecks/runtime/interpreting.rb +69 -0
  339. data/lib/hecks/runtime/loader.rb +143 -0
  340. data/lib/hecks/runtime/policy_interpreter.rb +366 -0
  341. data/lib/hecks/runtime/port_operation_interpreter.rb +210 -0
  342. data/lib/hecks/runtime/query_interpreter.rb +254 -0
  343. data/lib/hecks/runtime/reaction_invocation.rb +245 -0
  344. data/lib/hecks/runtime/read_model_interpreter.rb +266 -0
  345. data/lib/hecks/runtime/rebuild_sweep.rb +74 -0
  346. data/lib/hecks/runtime/reference_hop.rb +99 -0
  347. data/lib/hecks/runtime/refusal_wording.rb +124 -0
  348. data/lib/hecks/runtime/registry/saga_persistence.rb +70 -0
  349. data/lib/hecks/runtime/registry/verification.rb +158 -0
  350. data/lib/hecks/runtime/registry.rb +218 -0
  351. data/lib/hecks/runtime/remote_dispatcher.rb +143 -0
  352. data/lib/hecks/runtime/routing.rb +96 -0
  353. data/lib/hecks/runtime/saga_interpreter/correlation.rb +97 -0
  354. data/lib/hecks/runtime/saga_interpreter.rb +301 -0
  355. data/lib/hecks/runtime/storage_shape.rb +120 -0
  356. data/lib/hecks/runtime/tenant_check.rb +84 -0
  357. data/lib/hecks/runtime/tenant_scope.rb +55 -0
  358. data/lib/hecks/runtime/value/admission.rb +112 -0
  359. data/lib/hecks/runtime/value/coercion.rb +500 -0
  360. data/lib/hecks/runtime/value/invariant_violation.rb +5 -0
  361. data/lib/hecks/runtime/value.rb +125 -0
  362. data/lib/hecks/runtime.rb +95 -0
  363. data/lib/hecks/translation/audit/approval_digest.rb +31 -0
  364. data/lib/hecks/translation/audit/layer_one.rb +37 -0
  365. data/lib/hecks/translation/audit/layer_two.rb +77 -0
  366. data/lib/hecks/translation/audit/unfed_report.rb +42 -0
  367. data/lib/hecks/translation/audit.rb +70 -0
  368. data/lib/hecks/translation/reattest.rb +72 -0
  369. data/lib/hecks/translation/rule_compiler.rb +120 -0
  370. data/lib/hecks/translation/scaffold/differ.rb +183 -0
  371. data/lib/hecks/translation/scaffold/renderer.rb +41 -0
  372. data/lib/hecks/translation/scaffold/writer.rb +28 -0
  373. data/lib/hecks/translation/scaffold.rb +30 -0
  374. data/lib/hecks/translation.rb +11 -0
  375. data/lib/hecks/version.rb +16 -0
  376. data/lib/hecks/vocabulary.rb +213 -0
  377. data/lib/hecks.rb +118 -6
  378. metadata +401 -222
  379. data/bin/hecks +0 -7
  380. data/bin/hecks-package +0 -65
  381. data/bin/hecks_console +0 -12
  382. data/bin/hecks_serverless +0 -6
  383. data/lib/cli/build.rb +0 -14
  384. data/lib/cli/command_runner.rb +0 -28
  385. data/lib/cli/console.rb +0 -10
  386. data/lib/cli/generate.rb +0 -37
  387. data/lib/cli/hecks-cli.rb +0 -27
  388. data/lib/cli/test.rb +0 -57
  389. data/lib/console/commands.rb +0 -8
  390. data/lib/console/hecks-console.rb +0 -1
  391. data/lib/packager/README.md +0 -0
  392. data/lib/packager/app_runner.rb +0 -21
  393. data/lib/packager/args.rb +0 -26
  394. data/lib/packager/compatibility/fixnum.rb +0 -6
  395. data/lib/packager/hecks.rb +0 -39
  396. data/lib/packager/query_runner.rb +0 -21
  397. data/lib/packager/resources/Dockerfile +0 -11
  398. data/lib/packager/resources/app_binary +0 -7
  399. data/lib/packager/resources/bundle_config +0 -3
  400. data/lib/packager/resources/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz +0 -0
  401. data/lib/packager/resources/traveling-ruby-20150715-2.2.2-osx.tar.gz +0 -0
  402. data/lib/serverless/Domain +0 -32
  403. data/lib/serverless/cli.rb +0 -75
  404. data/lib/serverless/resources/command_name.js +0 -5
  405. data/lib/serverless/resources/environment.js +0 -7
  406. data/lib/serverless/resources/handler.js.tt +0 -28
  407. data/lib/serverless/resources/run_binary.js +0 -22
  408. data/lib/serverless/resources/serverless.yml +0 -20
@@ -0,0 +1,9 @@
1
+ Hecks.adapter "SqlitePersistence" do
2
+ port "persistence"
3
+ field :database
4
+ end
5
+
6
+ Hecks.adapter "SqliteProjection" do
7
+ port "projection"
8
+ field :database
9
+ end
@@ -0,0 +1,285 @@
1
+ require "json"
2
+ require "fileutils"
3
+
4
+ require_relative "sql_query_builder"
5
+ require_relative "sqlite/schema_builder"
6
+ require_relative "sqlite/codec"
7
+ require_relative "../../ports/persistence/append_only"
8
+ require_relative "../../query_specification/common/null_policy"
9
+ require_relative "../../query_specification/common/order_by"
10
+ require_relative "../../runtime/errors"
11
+ require_relative "../../runtime/event"
12
+ require_relative "../../runtime/instance"
13
+
14
+ module Hecks
15
+ module Adapters
16
+ # The SQLite store: one table per aggregate head, an append-only entry
17
+ # table beside it. The DDL lives in sqlite/schema_builder.rb, the
18
+ # column codec in sqlite/codec.rb, and the query compilation is the
19
+ # shared SqlQueryBuilder — this file supplies only SQLite's dialect.
20
+ class Sqlite
21
+ include SqlQueryBuilder
22
+ include SchemaBuilder
23
+ include Codec
24
+
25
+ SQL_TYPES = { "Integer" => "INTEGER", "Float" => "REAL" }.freeze
26
+
27
+ attr_reader :aggregate, :path
28
+
29
+ def persistence_capabilities = [:atomic_put]
30
+
31
+ def initialize(aggregate:, settings: {}, root: nil)
32
+ # LAZY, ON PURPOSE — a domain that never wires Sqlite should never
33
+ # need the gem installed. `require "hecks"` alone must not
34
+ # force a database client library nobody asked for.
35
+ require "sqlite3"
36
+
37
+ @aggregate = aggregate
38
+ @path = resolve_path(settings, root)
39
+ # THE OPTIONAL saga-persistence capability's own scoping column
40
+ # (§2/§4) — falls back to the aggregate's own name for a
41
+ # directly-instantiated adapter (specs), same fallback shape
42
+ # Postgres's own @domain already uses.
43
+ @domain = (settings[:domain] || settings["domain"] || aggregate.name).to_s
44
+
45
+ FileUtils.mkdir_p(File.dirname(@path))
46
+ @db = SQLite3::Database.new(@path)
47
+ @db.results_as_hash = true
48
+ # The append is the recovery commit point. Keep SQLite's fsync policy
49
+ # explicit instead of inheriting a process-wide pragma choice.
50
+ @db.execute("PRAGMA synchronous = FULL")
51
+
52
+ create_aggregate_table!
53
+ create_entry_table!
54
+ ensure_entry_operation_column!
55
+ ensure_entry_mirrors_column!
56
+ create_event_table!
57
+ create_saga_table!
58
+ end
59
+
60
+ def table = @aggregate.storage_name
61
+
62
+ def find(id)
63
+ row = @db.get_first_row("SELECT * FROM #{quoted_table} WHERE id = ?", [id.to_s])
64
+ return nil unless row
65
+
66
+ Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row))
67
+ end
68
+
69
+ # order_by IS A RUNTIME VALUE — see postgres.rb's own all for the
70
+ # full reasoning; whitelisted the identical way before it ever
71
+ # reaches order_expression.
72
+ def all(order_by: nil, direction: :asc)
73
+ order_sql = "ORDER BY id"
74
+ if order_by
75
+ name = order_by.to_s.split(".").first
76
+ raise Runtime::WiringError, "#{@aggregate.name} has no attribute #{order_by.inspect} to order by" unless @aggregate.lifecycle&.field.to_s == name || @aggregate.attribute(name)
77
+
78
+ spec = QuerySpecification::Common::OrderBy.new(field: order_by, direction: direction)
79
+ order_sql = "ORDER BY #{order_clause(spec, nil)}"
80
+ end
81
+
82
+ @db.execute("SELECT * FROM #{quoted_table} #{order_sql}").map do |row|
83
+ Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row))
84
+ end
85
+ end
86
+
87
+ def count = @db.get_first_value("SELECT COUNT(*) FROM #{quoted_table}").to_i
88
+
89
+ def append(entry)
90
+ @db.execute(
91
+ "INSERT INTO #{quoted_entry_table} (aggregate_id, operation, state, mirrors) VALUES (?, ?, ?, ?)",
92
+ [entry.id, entry.operation, JSON.generate(entry.state), JSON.generate(entry.mirrors)]
93
+ )
94
+ entry
95
+ end
96
+
97
+ def project(entry)
98
+ return @db.execute("DELETE FROM #{quoted_table} WHERE id = ?", [entry.id]) if entry.delete?
99
+
100
+ instance = Runtime::Instance.new(aggregate: @aggregate, id: entry.id, state: entry.state)
101
+ columns = (["id"] + persisted_fields.map { |field| field[:name].to_s }).map { |c| quote_ident(c) }
102
+ values = [instance.id.to_s] + persisted_fields.map { |field| encode_field(field, instance[field[:name]]) }
103
+ slots = Array.new(columns.size, "?").join(", ")
104
+
105
+ @db.execute(
106
+ "INSERT OR REPLACE INTO #{quoted_table} (#{columns.join(', ')}) VALUES (#{slots})",
107
+ values
108
+ )
109
+ instance
110
+ end
111
+
112
+ def entries
113
+ @db.execute("SELECT aggregate_id, operation, state, mirrors FROM #{quoted_entry_table} ORDER BY sequence").map do |row|
114
+ state = JSON.parse(row["state"])
115
+ Ports::Persistence::Entry.new(
116
+ operation: row["operation"] || "save",
117
+ id: row["aggregate_id"],
118
+ state: state&.transform_keys(&:to_sym),
119
+ mirrors: row["mirrors"] && JSON.parse(row["mirrors"])
120
+ )
121
+ end
122
+ end
123
+
124
+ def reset!
125
+ @db.execute("DELETE FROM #{quoted_table}")
126
+ @db.execute("DELETE FROM #{quoted_entry_table}")
127
+ self
128
+ end
129
+
130
+ def save(instance)
131
+ entry = Ports::Persistence::Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
132
+ append(entry)
133
+ project(entry)
134
+ end
135
+
136
+ # The outcome lookup, journal append and snapshot replacement share one
137
+ # SQLite transaction. The runtime performs no preliminary find; this
138
+ # adapter-native operation owns both concurrency and outcome reporting.
139
+ def atomic_put(entry, insert_only: false)
140
+ status = nil
141
+ @db.transaction do
142
+ exists = !@db.get_first_value("SELECT 1 FROM #{quoted_table} WHERE id = ?", [entry.id.to_s]).nil?
143
+ if insert_only && exists
144
+ status = :conflicted
145
+ next
146
+ end
147
+ status = exists ? :replaced : :inserted
148
+ append(entry)
149
+ project(entry)
150
+ end
151
+ status
152
+ end
153
+
154
+ def delete(id)
155
+ entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
156
+ append(entry)
157
+ project(entry)
158
+ true
159
+ end
160
+
161
+ def record_event(event)
162
+ @db.execute(
163
+ "INSERT INTO events (name, aggregate, aggregate_id, payload, occurred_at) VALUES (?, ?, ?, ?, ?)",
164
+ [event.name, event.aggregate, event.id.to_s, JSON.generate(event.payload), event.occurred_at]
165
+ )
166
+ end
167
+
168
+ def events
169
+ @db.execute("SELECT * FROM events ORDER BY id").map do |row|
170
+ Runtime::Event.new(
171
+ name: row["name"],
172
+ aggregate: row["aggregate"],
173
+ id: row["aggregate_id"],
174
+ payload: JSON.parse(row["payload"], symbolize_names: true),
175
+ occurred_at: row["occurred_at"]
176
+ )
177
+ end
178
+ end
179
+
180
+ # ── the OPTIONAL saga-persistence capability (§2) — reuses the
181
+ # DDL every SQLite-backed aggregate table already lives beside
182
+ # (`create_saga_table!`, `Sqlite::SchemaBuilder`, shared with D1).
183
+ # SQLite's `resolve_path` defaults to one `.db` file PER
184
+ # AGGREGATE unless a domain shares one `database` setting across
185
+ # its aggregates — since saga persistence resolves through
186
+ # whichever adapter instance backs the domain's FIRST aggregate
187
+ # (`Registry#saga_persistence`), this table ends up living inside
188
+ # THAT one aggregate's own file by default. Correct and durable
189
+ # either way; a domain that wants an obviously-named saga store
190
+ # already gets one by sharing `database` across its aggregates,
191
+ # the recommended, common case.
192
+ def save_saga(process_manager:, correlation:, state:, memory:)
193
+ @db.execute(
194
+ "INSERT OR REPLACE INTO hecks_saga_instances (domain, process_manager, correlation, state, memory) " \
195
+ "VALUES (?, ?, ?, ?, ?)",
196
+ [@domain, process_manager.to_s, correlation.to_s, state.to_s, JSON.generate(memory)]
197
+ )
198
+ end
199
+
200
+ def delete_saga(process_manager:, correlation:)
201
+ @db.execute(
202
+ "DELETE FROM hecks_saga_instances WHERE domain = ? AND process_manager = ? AND correlation = ?",
203
+ [@domain, process_manager.to_s, correlation.to_s]
204
+ )
205
+ end
206
+
207
+ def each_saga
208
+ return enum_for(:each_saga) unless block_given?
209
+
210
+ @db.execute(
211
+ "SELECT process_manager, correlation, state, memory FROM hecks_saga_instances WHERE domain = ?",
212
+ [@domain]
213
+ ).each do |row|
214
+ yield row["process_manager"], row["correlation"], row["state"],
215
+ JSON.parse(row["memory"], symbolize_names: true)
216
+ end
217
+ end
218
+
219
+ private
220
+
221
+ # ── SqlQueryBuilder's dialect hooks ─────────────────────────────
222
+
223
+ def select_list = "*"
224
+ def from_relation = quoted_table
225
+ def dialect_name = "SQLite"
226
+ def empty_in_clause = "0"
227
+
228
+ def placeholder(binds, value)
229
+ binds << value
230
+ "?"
231
+ end
232
+
233
+ def contains_clause(expression, placeholder)
234
+ "instr(#{expression}, #{placeholder}) > 0"
235
+ end
236
+
237
+ def list_contains_clause(column, member, placeholder)
238
+ target = member.empty? ? "json_each.value" : "json_extract(json_each.value, '$.#{member}')"
239
+ "EXISTS (SELECT 1 FROM json_each(#{quote_ident(column)}) WHERE #{target} = #{placeholder})"
240
+ end
241
+
242
+ def plain_column(name) = quote_ident(name)
243
+
244
+ def nested_expression(name, path, member)
245
+ json_path = path.empty? ? "$.#{member || 'value'}" : "$.#{path.join('.')}"
246
+ "json_extract(#{quote_ident(name)}, '#{json_path}')"
247
+ end
248
+
249
+ # SQLite has no bare OFFSET — LIMIT -1 is its own documented
250
+ # unbounded spelling, exactly for this case.
251
+ def unbounded_limit = " LIMIT -1"
252
+
253
+ def order_clause(order_by, policy)
254
+ QuerySpecification::Common::NullPolicy.sql_order(query_expression(order_by.field), order_by.direction, policy)
255
+ end
256
+
257
+ def execute_query(sql, binds)
258
+ @db.execute(sql, binds).map { |row| Runtime::Instance.new(aggregate: @aggregate, id: row["id"], state: decode(row)) }
259
+ end
260
+
261
+ # ── the rest of the dialect ─────────────────────────────────────
262
+
263
+ def quote_ident(name)
264
+ %("#{name.to_s.gsub('"', '""')}")
265
+ end
266
+
267
+ def quoted_table = quote_ident(table)
268
+ def entry_table = "#{table}_entries"
269
+ def quoted_entry_table = quote_ident(entry_table)
270
+
271
+ def resolve_path(settings, root)
272
+ declared = settings[:database] || settings["database"] || "data/#{table}.db"
273
+ return declared if declared.start_with?("/")
274
+
275
+ File.join(root || Dir.pwd, declared)
276
+ end
277
+ end
278
+
279
+ # Port-specific bindings share SQLite's storage mechanics but advertise
280
+ # only one operational contract each.
281
+ class SqlitePersistence < Sqlite; end
282
+ end
283
+ end
284
+
285
+ require_relative "sqlite/projection"
@@ -0,0 +1,3 @@
1
+ Hecks.adapter "SystemClock" do
2
+ port "clock"
3
+ end
@@ -0,0 +1,14 @@
1
+ module Hecks
2
+ module Adapters
3
+ # The real `clock` fulfillment — the machine's own time, in seconds.
4
+ #
5
+ # Whole seconds on purpose. The sublanguage does integer arithmetic, a
6
+ # staleness window is measured in minutes, and sub-second precision in a
7
+ # durable ledger is precision nobody reads and every diff has to ignore.
8
+ module SystemClock
9
+ module_function
10
+
11
+ def now = Time.now.to_i
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ module Hecks
2
+ module Adapters
3
+ # The driven side — every store or reader an adapter declaration can
4
+ # bind. A small adapter is one file beside this one; sqlite, postgres
5
+ # and heki keep a directory for their supporting cast. Each `.adapter`
6
+ # file alongside is the DSL declaration the grammar bootstrap and the
7
+ # Folder adapter load as data.
8
+ end
9
+ end
10
+
11
+ require_relative "driven/memory"
12
+ require_relative "driven/sqlite"
13
+ require_relative "driven/postgres"
14
+ require_relative "driven/postgres_era"
15
+ require_relative "driven/lambda"
16
+ require_relative "driven/heki"
17
+ require_relative "driven/prism"
18
+ require_relative "driven/folder"
19
+ require_relative "driven/d1"
20
+ require_relative "driven/mock_stripe_adapter"
21
+ require_relative "driven/secure_random_identity"
22
+ require_relative "driven/system_clock"
23
+ # `SequentialIdentity` — the deterministic identity_generation test
24
+ # double — is NOT required here on purpose. It lives at
25
+ # spec/fixtures/sequential_identity.{adapter,rb}, loaded explicitly by
26
+ # whichever spec wants it: this file's `require_relative` list is what
27
+ # `Folder#load_library`'s `.adapter` glob backs, and `.adapter` DSL
28
+ # declarations register into every registry any real `Hecks.boot` ever
29
+ # builds. Two adapters answering `identity_generation` unconditionally
30
+ # would make the port permanently ambiguous — `Ports::IdentityGeneration
31
+ # .adapter` refuses to choose between more than one — for every
32
+ # consumer, forever, not just specs that want the deterministic one.
33
+ require_relative "driven/governance_authorization"
34
+ require_relative "driven/identity_registry"
35
+ require_relative "driven/google_authentication"
36
+ require_relative "driven/claude_code"
@@ -0,0 +1,6 @@
1
+ module Hecks
2
+ module Adapters
3
+ end
4
+ end
5
+
6
+ require_relative "adapters/driven"
@@ -0,0 +1,96 @@
1
+ require_relative "ir"
2
+
3
+ # The authoring surface for `Hecks.behaviors "Name" do ... end` — one
4
+ # `test "description" do ... end` block per case, `tests`/`setup`/`input`/
5
+ # `expect` inside. `instance_eval`-based, the same shape every other
6
+ # hecks DSL builder uses (`WorldBuilder`, `HecksagonBuilder`).
7
+ module Hecks
8
+ module Behaviors
9
+ # Raised at `Hecks.behaviors` build time — a missing `vision` or
10
+ # `loads` line names the fix directly rather than failing later, deep
11
+ # inside a boot, over a suite that was never going to be scoped.
12
+ class Malformed < StandardError; end
13
+
14
+ class TestCaseBuilder
15
+ def initialize(description)
16
+ @description = description
17
+ @tests_command = nil
18
+ @on_aggregate = nil
19
+ @kind = :command
20
+ @setups = []
21
+ @input = {}
22
+ @expect = {}
23
+ end
24
+
25
+ def tests(command, on: nil, kind: :command)
26
+ @tests_command = command
27
+ @on_aggregate = on
28
+ @kind = kind
29
+ end
30
+
31
+ def setup(command, **kwargs)
32
+ @setups << TestSetup.new(command: command, args: kwargs)
33
+ end
34
+
35
+ def input(**kwargs) = @input.merge!(kwargs)
36
+ def expect(**kwargs) = @expect.merge!(kwargs)
37
+
38
+ def build
39
+ unless @tests_command
40
+ raise Malformed, "test #{@description.inspect} never calls `tests` — " \
41
+ "say which command or query this example exercises"
42
+ end
43
+
44
+ TestCase.new(description: @description, tests_command: @tests_command,
45
+ on_aggregate: @on_aggregate, kind: @kind,
46
+ setups: @setups, input: @input, expect: @expect)
47
+ end
48
+ end
49
+
50
+ class BehaviorsBuilder
51
+ def initialize(name, source_path:)
52
+ @name = name
53
+ @source_path = source_path
54
+ @source_dir = File.dirname(source_path)
55
+ @vision = nil
56
+ @loads = nil
57
+ @tests = []
58
+ end
59
+
60
+ def vision(text) = @vision = text
61
+
62
+ # Relative to THIS `.behaviors` file, never to the filesystem's cwd
63
+ # or a same-stem convention — scope is a fact this file declares,
64
+ # not one a runner infers.
65
+ def loads(*paths)
66
+ @loads = paths.map { |path| File.expand_path(path, @source_dir) }
67
+ end
68
+
69
+ def test(description, &block)
70
+ builder = TestCaseBuilder.new(description)
71
+ builder.instance_eval(&block) if block
72
+ @tests << builder.build
73
+ end
74
+
75
+ def build
76
+ unless @vision
77
+ raise Malformed, "#{@source_path}: no `vision \"...\"` — say in one line " \
78
+ "what this suite is examples of"
79
+ end
80
+ unless @loads
81
+ raise Malformed, "#{@source_path}: no `loads \"...\"` — a behaviors file " \
82
+ "must declare exactly which files to boot"
83
+ end
84
+
85
+ BehaviorsSuite.new(name: @name, vision: @vision, loads: @loads,
86
+ tests: @tests, path: @source_path)
87
+ end
88
+
89
+ def self.build(name, source_path:, &block)
90
+ builder = new(name, source_path: source_path)
91
+ builder.instance_eval(&block) if block
92
+ builder.build
93
+ end
94
+ end
95
+ end
96
+ end