hecks 1.3.0 → 1.5.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.
- checksums.yaml +4 -4
- data/lib/hecks/adapters/driven/claude_code.rb +72 -7
- data/lib/hecks/adapters/driven/d1.rb +187 -23
- data/lib/hecks/adapters/driven/folder.rb +83 -10
- data/lib/hecks/adapters/driven/google_authentication.rb +33 -12
- data/lib/hecks/adapters/driven/governance_authorization.rb +87 -18
- data/lib/hecks/adapters/driven/heki/journal.rb +13 -4
- data/lib/hecks/adapters/driven/heki/saga_store.rb +56 -10
- data/lib/hecks/adapters/driven/heki/snapshot.rb +1 -1
- data/lib/hecks/adapters/driven/heki.rb +106 -9
- data/lib/hecks/adapters/driven/identity_registry.rb +12 -2
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +25 -3
- data/lib/hecks/adapters/driven/in_process_key_vault.adapter +3 -0
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +53 -0
- data/lib/hecks/adapters/driven/lambda/client.rb +67 -14
- data/lib/hecks/adapters/driven/lambda.rb +82 -35
- data/lib/hecks/adapters/driven/local_storage.rb +83 -10
- data/lib/hecks/adapters/driven/memory.rb +205 -9
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +21 -1
- data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
- data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
- data/lib/hecks/adapters/driven/postgres.rb +175 -28
- data/lib/hecks/adapters/driven/prism.rb +50 -11
- data/lib/hecks/adapters/driven/secure_random_identity.rb +3 -0
- data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
- data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
- data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
- data/lib/hecks/adapters/driven/sqlite.rb +181 -21
- data/lib/hecks/adapters/driven/system_clock.rb +3 -0
- data/lib/hecks/adapters/driven/tenant_provisioner.adapter +3 -0
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +66 -0
- data/lib/hecks/adapters/driven.rb +6 -4
- data/lib/hecks/adapters/driving/github_webhook.rb +31 -18
- data/lib/hecks/behaviors/dsl.rb +60 -2
- data/lib/hecks/behaviors/expectations.rb +190 -29
- data/lib/hecks/behaviors/ir.rb +12 -1
- data/lib/hecks/behaviors/rspec.rb +9 -1
- data/lib/hecks/behaviors/runner.rb +21 -2
- data/lib/hecks/behaviors.rb +9 -1
- data/lib/hecks/bluebook/aggregate.rb +43 -13
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +17 -10
- data/lib/hecks/bluebook/assembly/build.rb +26 -5
- data/lib/hecks/bluebook/assembly/contract.rb +98 -23
- data/lib/hecks/bluebook/assembly/contracts.rb +59 -52
- data/lib/hecks/bluebook/assembly/marks.rb +159 -30
- data/lib/hecks/bluebook/assembly/specializer.rb +38 -21
- data/lib/hecks/bluebook/assembly.rb +32 -14
- data/lib/hecks/bluebook/attribute.rb +26 -12
- data/lib/hecks/bluebook/behaviour/aggregate.rb +43 -11
- data/lib/hecks/bluebook/behaviour/attribute.rb +18 -5
- data/lib/hecks/bluebook/behaviour/chapter.rb +76 -5
- data/lib/hecks/bluebook/behaviour/command.rb +55 -25
- data/lib/hecks/bluebook/behaviour/domain_port.rb +27 -7
- data/lib/hecks/bluebook/behaviour/entity.rb +20 -8
- data/lib/hecks/bluebook/behaviour/hexagon.rb +30 -4
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +27 -6
- data/lib/hecks/bluebook/behaviour/policy.rb +42 -17
- data/lib/hecks/bluebook/behaviour/process_manager.rb +39 -8
- data/lib/hecks/bluebook/behaviour/query.rb +6 -1
- data/lib/hecks/bluebook/behaviour/read_model.rb +29 -8
- data/lib/hecks/bluebook/behaviour/traits.rb +48 -12
- data/lib/hecks/bluebook/behaviour/value_object.rb +21 -9
- data/lib/hecks/bluebook/capabilities.rb +27 -0
- data/lib/hecks/bluebook/chapter.rb +51 -9
- data/lib/hecks/bluebook/command.rb +62 -17
- data/lib/hecks/bluebook/domain_port.rb +34 -9
- data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +282 -123
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +112 -75
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +81 -2
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +486 -117
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +179 -47
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +284 -122
- data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
- data/lib/hecks/bluebook/dsl/entity_builder.rb +191 -61
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +130 -30
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +38 -21
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
- data/lib/hecks/bluebook/dsl/policy_builder.rb +86 -36
- data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +111 -47
- data/lib/hecks/bluebook/dsl/query_builder.rb +37 -8
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +127 -52
- data/lib/hecks/bluebook/dsl/rule_reference.rb +97 -43
- data/lib/hecks/bluebook/dsl/translation_builder.rb +150 -44
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +68 -20
- data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
- data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
- data/lib/hecks/bluebook/entity.rb +40 -11
- data/lib/hecks/bluebook/expression/ast_json.rb +128 -36
- data/lib/hecks/bluebook/expression/ast_reader.rb +32 -3
- data/lib/hecks/bluebook/expression/canonical_form.rb +55 -16
- data/lib/hecks/bluebook/expression/evaluator.rb +221 -43
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +54 -18
- data/lib/hecks/bluebook/expression/resolver.rb +369 -128
- data/lib/hecks/bluebook/hexagon.rb +35 -1
- data/lib/hecks/bluebook/lifecycle.rb +12 -1
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +2 -1
- data/lib/hecks/bluebook/meta_validator/judge.rb +126 -108
- data/lib/hecks/bluebook/meta_validator/plan.rb +81 -46
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +3 -2
- data/lib/hecks/bluebook/meta_validator/readings.rb +200 -50
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +68 -41
- data/lib/hecks/bluebook/meta_validator/shapes.rb +166 -21
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +286 -46
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +11 -10
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -5
- data/lib/hecks/bluebook/meta_validator.rb +235 -139
- data/lib/hecks/bluebook/model_check.rb +434 -104
- data/lib/hecks/bluebook/pattern_subset.rb +32 -10
- data/lib/hecks/bluebook/policy.rb +15 -13
- data/lib/hecks/bluebook/process_manager.rb +27 -14
- data/lib/hecks/bluebook/project_discovery.rb +5 -0
- data/lib/hecks/bluebook/project_loader.rb +40 -0
- data/lib/hecks/bluebook/project_register.rb +50 -6
- data/lib/hecks/bluebook/query.rb +31 -4
- data/lib/hecks/bluebook/read_model.rb +35 -15
- data/lib/hecks/bluebook/reference.rb +26 -13
- data/lib/hecks/bluebook/smoke_test.rb +46 -23
- data/lib/hecks/bluebook/synthesizer.rb +46 -12
- data/lib/hecks/bluebook/translation.rb +34 -5
- data/lib/hecks/bluebook/value_object.rb +29 -11
- data/lib/hecks/bluebook.rb +5 -6
- data/lib/hecks/codemod.rb +138 -50
- data/lib/hecks/construct.rb +21 -7
- data/lib/hecks/corpus.rb +438 -0
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +19 -0
- data/lib/hecks/doc/reference.rb +200 -31
- data/lib/hecks/embryonaut_bluebook.rb +38 -15
- data/lib/hecks/facade/cli_door.rb +69 -10
- data/lib/hecks/facade/cli_runner.rb +105 -24
- data/lib/hecks/facade/command_request.rb +23 -0
- data/lib/hecks/facade/handle.rb +155 -35
- data/lib/hecks/facade/json_door.rb +106 -25
- data/lib/hecks/facade/surface/aggregate_door.rb +50 -27
- data/lib/hecks/facade/surface/chapter.rb +26 -17
- data/lib/hecks/facade/surface.rb +16 -3
- data/lib/hecks/facade.rb +15 -4
- data/lib/hecks/forms/app.rb +46 -30
- data/lib/hecks/forms/command_form_renderer.rb +70 -9
- data/lib/hecks/forms/field_renderer.rb +142 -6
- data/lib/hecks/forms/field_shape.rb +183 -19
- data/lib/hecks/forms/html.rb +51 -7
- data/lib/hecks/forms/index_renderer.rb +14 -2
- data/lib/hecks/forms/page.rb +14 -0
- data/lib/hecks/forms/params.rb +120 -23
- data/lib/hecks/forms/port_argument.rb +14 -2
- data/lib/hecks/forms/query_form_renderer.rb +65 -2
- data/lib/hecks/forms/record_renderer.rb +60 -2
- data/lib/hecks/forms/record_table.rb +28 -1
- data/lib/hecks/forms/reference_options.rb +24 -0
- data/lib/hecks/forms/value_object_shape.rb +13 -3
- data/lib/hecks/forms.rb +24 -4
- data/lib/hecks/fqn.rb +59 -1
- data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
- data/lib/hecks/framework/bluebook/privacy.bluebook +155 -0
- data/lib/hecks/framework/oidc.json +15 -0
- data/lib/hecks/framework.rb +79 -25
- data/lib/hecks/freezer.rb +27 -11
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +241 -106
- data/lib/hecks/fuzzing/combination_miner.rb +178 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +241 -45
- data/lib/hecks/fuzzing/coverage_campaign.rb +161 -0
- data/lib/hecks/fuzzing/differential.rb +192 -0
- data/lib/hecks/fuzzing/domain_generator.rb +871 -0
- data/lib/hecks/fuzzing/era_boundary.rb +68 -19
- data/lib/hecks/fuzzing/form_census.rb +121 -20
- data/lib/hecks/fuzzing/generated_domain_check.rb +171 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +45 -6
- data/lib/hecks/fuzzing/isolated_boot.rb +137 -80
- data/lib/hecks/fuzzing/nondeterministic.rb +79 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +111 -21
- data/lib/hecks/fuzzing/properties/corrections.rb +34 -9
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +300 -51
- data/lib/hecks/fuzzing/properties/guards.rb +86 -42
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +80 -32
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +40 -35
- data/lib/hecks/fuzzing/properties/outbox.rb +70 -32
- data/lib/hecks/fuzzing/properties/querying.rb +82 -28
- data/lib/hecks/fuzzing/properties.rb +84 -51
- data/lib/hecks/fuzzing/qa_settings.rb +164 -0
- data/lib/hecks/fuzzing/replay.rb +241 -133
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -28
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +139 -0
- data/lib/hecks/fuzzing/self_consistency.rb +315 -137
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +46 -40
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +59 -32
- data/lib/hecks/fuzzing/sequence_generator.rb +158 -23
- data/lib/hecks/fuzzing/shrinker.rb +309 -0
- data/lib/hecks/fuzzing/structural_skips.rb +37 -130
- data/lib/hecks/fuzzing/sweep_depth.rb +12 -4
- data/lib/hecks/fuzzing/target_capabilities.rb +107 -29
- data/lib/hecks/fuzzing/value_generator.rb +110 -22
- data/lib/hecks/fuzzing.rb +5 -0
- data/lib/hecks/grammar/evolve.rb +188 -12
- data/lib/hecks/grammar.rb +53 -7
- data/lib/hecks/ir.rb +51 -20
- data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
- data/lib/hecks/language/bluebook/policy.bluebook +11 -1
- data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +11 -0
- data/lib/hecks/language/oidc.json +5 -0
- data/lib/hecks/literal.rb +41 -9
- data/lib/hecks/naming.rb +112 -31
- data/lib/hecks/ports/access_control.rb +53 -2
- data/lib/hecks/ports/agent/answers.rb +83 -6
- data/lib/hecks/ports/agent.rb +119 -35
- data/lib/hecks/ports/authentication.rb +44 -4
- data/lib/hecks/ports/authorization.rb +50 -11
- data/lib/hecks/ports/clock.rb +42 -23
- data/lib/hecks/ports/extraction.rb +16 -0
- data/lib/hecks/ports/identity_assignment.rb +23 -2
- data/lib/hecks/ports/identity_generation.rb +17 -3
- data/lib/hecks/ports/identity_resolution.rb +17 -1
- data/lib/hecks/ports/key_vault.port +6 -0
- data/lib/hecks/ports/key_vault.rb +58 -0
- data/lib/hecks/ports/loading.rb +4 -0
- data/lib/hecks/ports/persistence/append_only.rb +172 -8
- data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
- data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
- data/lib/hecks/ports/persistence/execution.rb +4 -0
- data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
- data/lib/hecks/ports/persistence/plugin.rb +42 -4
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +34 -5
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +95 -6
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +48 -8
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +58 -19
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +96 -5
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +15 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +9 -1
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
- data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
- data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
- data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
- data/lib/hecks/ports/persistence/state_codec.rb +319 -0
- data/lib/hecks/ports/persistence.rb +36 -1
- data/lib/hecks/ports/projection.rb +61 -7
- data/lib/hecks/ports/query/in_memory.rb +41 -8
- data/lib/hecks/ports/query/ordering.rb +21 -6
- data/lib/hecks/ports/query.rb +35 -0
- data/lib/hecks/ports.rb +1 -0
- data/lib/hecks/projections/bootstrap_table.rb +147 -0
- data/lib/hecks/projections/diagrams.rb +315 -79
- data/lib/hecks/projections/glossary/html.rb +91 -3
- data/lib/hecks/projections/glossary/markdown.rb +50 -3
- data/lib/hecks/projections/glossary/mermaid.rb +49 -1
- data/lib/hecks/projections/glossary/sections.rb +1 -1
- data/lib/hecks/projections/glossary/sentences.rb +110 -5
- data/lib/hecks/projections/glossary.rb +173 -31
- data/lib/hecks/projections/ir.rb +1 -1
- data/lib/hecks/projections/model/deviations.rb +62 -17
- data/lib/hecks/projections/model.rb +75 -21
- data/lib/hecks/projections/oidc.rb +45 -8
- data/lib/hecks/projections/parser_table.rb +53 -12
- data/lib/hecks/projections/reference.rb +15 -3
- data/lib/hecks/projections/rust_vocabulary.rb +646 -0
- data/lib/hecks/projections/shape.rb +10 -2
- data/lib/hecks/projections/statements.rb +69 -22
- data/lib/hecks/projections/vocabulary.rb +26 -9
- data/lib/hecks/projections.rb +5 -3
- data/lib/hecks/projector/cli_projector.rb +245 -37
- data/lib/hecks/projector/docs_projector.rb +154 -28
- data/lib/hecks/projector/exporter.rb +104 -29
- data/lib/hecks/projector/ir_projector.rb +7 -1
- data/lib/hecks/projector/narrate_projector.rb +144 -23
- data/lib/hecks/projector/target.rb +42 -18
- data/lib/hecks/projector.rb +86 -18
- data/lib/hecks/query_ir.rb +94 -47
- data/lib/hecks/query_specification/common/comparators.rb +19 -3
- data/lib/hecks/query_specification/common/comparison.rb +109 -27
- data/lib/hecks/query_specification/common/dsl.rb +65 -9
- data/lib/hecks/query_specification/common/null_policy.rb +61 -15
- data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
- data/lib/hecks/query_specification/common/options.rb +25 -0
- data/lib/hecks/query_specification/field_path.rb +69 -15
- data/lib/hecks/query_specification/hop_path.rb +57 -20
- data/lib/hecks/query_specification/read_model/specification.rb +4 -0
- data/lib/hecks/rendering.rb +9 -3
- data/lib/hecks/router/namespace_installer.rb +16 -3
- data/lib/hecks/router.rb +56 -1
- data/lib/hecks/runtime/aggregate_lock.rb +20 -11
- data/lib/hecks/runtime/boot_gates.rb +21 -3
- data/lib/hecks/runtime/caller.rb +40 -8
- data/lib/hecks/runtime/capability_graph.rb +13 -2
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +40 -41
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +45 -67
- data/lib/hecks/runtime/command_interpreter.rb +195 -113
- data/lib/hecks/runtime/command_rules/admissibility.rb +231 -80
- data/lib/hecks/runtime/command_rules/arithmetic.rb +154 -96
- data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
- data/lib/hecks/runtime/command_rules/emission.rb +18 -1
- data/lib/hecks/runtime/command_rules/references.rb +145 -55
- data/lib/hecks/runtime/command_rules.rb +3 -0
- data/lib/hecks/runtime/dependency_planning.rb +56 -11
- data/lib/hecks/runtime/dispatcher.rb +263 -92
- data/lib/hecks/runtime/entity_element.rb +304 -67
- data/lib/hecks/runtime/entity_interpreter.rb +149 -88
- data/lib/hecks/runtime/errors.rb +37 -23
- data/lib/hecks/runtime/event.rb +15 -10
- data/lib/hecks/runtime/identity.rb +91 -23
- data/lib/hecks/runtime/instance.rb +103 -18
- data/lib/hecks/runtime/interpreting.rb +24 -16
- data/lib/hecks/runtime/invocation.rb +358 -0
- data/lib/hecks/runtime/loader.rb +105 -19
- data/lib/hecks/runtime/outbox.rb +164 -26
- data/lib/hecks/runtime/policy_interpreter.rb +73 -60
- data/lib/hecks/runtime/port_operation_interpreter.rb +42 -19
- data/lib/hecks/runtime/query_interpreter.rb +93 -74
- data/lib/hecks/runtime/reaction_invocation.rb +73 -28
- data/lib/hecks/runtime/read_model_interpreter.rb +60 -44
- data/lib/hecks/runtime/rebuild_sweep.rb +32 -4
- data/lib/hecks/runtime/reference_hop.rb +48 -6
- data/lib/hecks/runtime/refusal_wording.rb +142 -115
- data/lib/hecks/runtime/registry/saga_persistence.rb +32 -21
- data/lib/hecks/runtime/registry/verification.rb +153 -28
- data/lib/hecks/runtime/registry.rb +202 -32
- data/lib/hecks/runtime/remote_dispatcher.rb +125 -24
- data/lib/hecks/runtime/routing.rb +36 -154
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +25 -27
- data/lib/hecks/runtime/saga_interpreter.rb +90 -76
- data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
- data/lib/hecks/runtime/tenant_check.rb +33 -13
- data/lib/hecks/runtime/tenant_scope.rb +23 -5
- data/lib/hecks/runtime/value/admission.rb +75 -30
- data/lib/hecks/runtime/value/coercion.rb +555 -142
- data/lib/hecks/runtime/value/entity_list_coercion.rb +132 -60
- data/lib/hecks/runtime/value.rb +71 -21
- data/lib/hecks/runtime.rb +39 -7
- data/lib/hecks/storehouse.rb +368 -72
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +130 -0
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +32 -0
- data/lib/hecks/version.rb +3 -3
- data/lib/hecks/vocabulary.rb +205 -4
- data/lib/hecks.rb +91 -11
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +19 -11
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +24 -12
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +38 -14
- metadata +28 -2
|
@@ -11,6 +11,14 @@ module Hecks
|
|
|
11
11
|
class << self
|
|
12
12
|
attr_accessor :resolver
|
|
13
13
|
|
|
14
|
+
# Installs a resolver for the duration of a block, restoring the earlier one afterwards
|
|
15
|
+
# even if the block raises.
|
|
16
|
+
#
|
|
17
|
+
# @param resolver [#call] called with the missing constant's name as a Symbol; whatever
|
|
18
|
+
# it returns is what the bare constant evaluates to
|
|
19
|
+
# @yield the DSL code whose undeclared constants the resolver should answer
|
|
20
|
+
# @yieldreturn [Object] any value; it becomes this method's result
|
|
21
|
+
# @return [Object] whatever the block returns
|
|
14
22
|
def with(resolver)
|
|
15
23
|
previous = @resolver
|
|
16
24
|
@resolver = resolver
|
|
@@ -19,45 +27,63 @@ module Hecks
|
|
|
19
27
|
@resolver = previous
|
|
20
28
|
end
|
|
21
29
|
|
|
30
|
+
# Reports whether a resolver is installed, meaning code is running inside a DSL block.
|
|
31
|
+
#
|
|
32
|
+
# @return [Boolean] true inside a `with` block, or after `resolver=` set one directly
|
|
22
33
|
def active? = !@resolver.nil?
|
|
23
34
|
end
|
|
24
35
|
|
|
25
|
-
#
|
|
36
|
+
# The scoped-constant bridge (ADR 0025, docs/dsl-work-slices.md's
|
|
26
37
|
# S0b) — a Symbol cannot answer `::`, so `Account::Debit` and
|
|
27
38
|
# `admits: Account::LedgerDirection` could never resolve past
|
|
28
|
-
# their
|
|
39
|
+
# their first segment while `Account` returned a bare Symbol
|
|
29
40
|
# (`resolver = ->(const) { const }`, bluebook_builder.rb's own
|
|
30
|
-
# comment on why that was right for a
|
|
41
|
+
# comment on why that was right for a bare name): Ruby's `::`
|
|
31
42
|
# operator raises `TypeError` on the returned value before any
|
|
32
43
|
# DSL code runs at all, unless that value is itself a Module.
|
|
33
44
|
#
|
|
34
|
-
# A
|
|
35
|
-
# that reason — nothing else answers `::`. Every
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
45
|
+
# A real `Module` subclass, not a decorated Symbol, for exactly
|
|
46
|
+
# that reason — nothing else answers `::`. Every consumer of a
|
|
47
|
+
# bareword type keeps working duck-typed: `Attribute#spell`'s
|
|
48
|
+
# `type.is_a?(Module)` branch fires for one of these where a
|
|
49
|
+
# bare Symbol falls to `type.to_s`, and `Naming.demodulise`
|
|
50
|
+
# (`path.split("::").last`) gives the identical string either
|
|
51
|
+
# way for a single segment — the two branches are equivalent
|
|
52
|
+
# for a name with no `::` in it, which is every unscoped
|
|
53
|
+
# bareword.
|
|
43
54
|
class ScopedConstant < Module
|
|
55
|
+
# Wraps a constant path, the form a `ConstShim` resolver hands back for a bareword.
|
|
56
|
+
#
|
|
57
|
+
# @param path [Symbol, String] one segment such as `:Account`, or a `::`-joined path
|
|
58
|
+
# @return [Bluebook::DSL::ConstShim::ScopedConstant] a module standing in for that path
|
|
44
59
|
def self.for(path) = new(path.to_s)
|
|
45
60
|
|
|
61
|
+
# @param path [String] the constant path this module stands in for
|
|
46
62
|
def initialize(path)
|
|
47
63
|
super()
|
|
48
64
|
@path = path
|
|
49
65
|
end
|
|
50
66
|
|
|
51
|
-
#
|
|
67
|
+
# Extends the path by one segment, so `Account::Debit` resolves past `Account`.
|
|
68
|
+
#
|
|
69
|
+
# One more segment, the same way an unresolved const anywhere
|
|
52
70
|
# else does — `Account::Debit::Anything` keeps chaining rather
|
|
53
71
|
# than refusing, since nothing here knows how deep a reference
|
|
54
72
|
# is meant to go; the DSL keyword that finally reads `.to_s`
|
|
55
73
|
# is the one place that does.
|
|
74
|
+
#
|
|
75
|
+
# @param name [Symbol] the segment written after `::`
|
|
76
|
+
# @return [Bluebook::DSL::ConstShim::ScopedConstant] a new constant for the longer path
|
|
56
77
|
def const_missing(name) = ScopedConstant.for("#{@path}::#{name}")
|
|
57
78
|
|
|
58
79
|
def to_s = @path
|
|
59
80
|
def to_sym = @path.to_sym
|
|
60
81
|
def inspect = @path
|
|
82
|
+
|
|
83
|
+
# Exposes the raw path under a name no ordinary `Module` answers, so `==` can compare
|
|
84
|
+
# two scoped constants without going through `to_s`.
|
|
85
|
+
#
|
|
86
|
+
# @return [String] the `::`-joined path, such as `"Account::Debit"`
|
|
61
87
|
def hecks_path = @path
|
|
62
88
|
|
|
63
89
|
def ==(other) = other.is_a?(ScopedConstant) ? @path == other.hecks_path : @path.to_sym == other
|
|
@@ -65,15 +91,20 @@ module Hecks
|
|
|
65
91
|
def hash = @path.hash
|
|
66
92
|
end
|
|
67
93
|
|
|
68
|
-
# A
|
|
94
|
+
# A scoped name is written as text, not as a constant path — see the
|
|
69
95
|
# note on `admits:` in AttributeCollector. A resolver returning a
|
|
70
96
|
# Module (so that `Vocabulary::QueryComparator` reaches a second
|
|
71
97
|
# `const_missing`) was tried and cannot be made to hold : `Facade::
|
|
72
|
-
# Surface` installs
|
|
98
|
+
# Surface` installs every aggregate name as a top-level constant, so
|
|
73
99
|
# once any facade is built, `Vocabulary` resolves to that real module
|
|
74
100
|
# and never reaches this hook at all. A spelling that works only
|
|
75
101
|
# before a facade exists is worse than one that always works.
|
|
76
102
|
module Hook
|
|
103
|
+
# Answers an undeclared top-level constant from the active resolver, if there is one.
|
|
104
|
+
#
|
|
105
|
+
# @param name [Symbol] the missing constant's name
|
|
106
|
+
# @return [Object] whatever the active resolver returns for `name`
|
|
107
|
+
# @raise [NameError] if no resolver is installed, as Ruby raises for any unknown constant
|
|
77
108
|
def const_missing(name)
|
|
78
109
|
resolver = ConstShim.resolver
|
|
79
110
|
resolver ? resolver.call(name) : super
|
|
@@ -14,21 +14,27 @@ module Hecks
|
|
|
14
14
|
|
|
15
15
|
include WordGate
|
|
16
16
|
|
|
17
|
-
# `legacy_bare_port:` —
|
|
17
|
+
# `legacy_bare_port:` — only `Hecks.port`'s own top-level method
|
|
18
18
|
# (lib/hecks.rb) passes `true`. `PortBuilder#build` never refused
|
|
19
19
|
# an empty build (no verb, no signal, nothing) — `Port.new(verb:
|
|
20
20
|
# nil, signal: :reply)` is a real, allowed shape dsl_spec.rb's own
|
|
21
21
|
# "a port" tests rely on (`signal`-only, no `verb` at all). The
|
|
22
|
-
#
|
|
23
|
-
# (`HecksagonBuilder#port_impl`) callers both reach this
|
|
22
|
+
# aggregate-scoped (`BindingProxy#port`) and hecksagon-root
|
|
23
|
+
# (`HecksagonBuilder#port_impl`) callers both reach this same
|
|
24
24
|
# class with `owner: nil` too when they're building the bare-verb
|
|
25
|
-
# shape (`port_impl`'s own root-level port can be
|
|
25
|
+
# shape (`port_impl`'s own root-level port can be either shape,
|
|
26
26
|
# decided only after `build` returns) — so `owner.nil?` cannot be
|
|
27
27
|
# the discriminator between "old Hecks.port semantics" and "real
|
|
28
28
|
# DomainPort semantics"; those two callers correctly want the
|
|
29
29
|
# stricter "declares no verb and no operations" refusal `build`
|
|
30
30
|
# already raises below, unchanged. Only the literal top-level
|
|
31
31
|
# `.port` file caller wants the older, looser rule.
|
|
32
|
+
#
|
|
33
|
+
# @param name [String] the port's name
|
|
34
|
+
# @param owner [String, nil] name of the aggregate the port is declared on, handed to
|
|
35
|
+
# each operation's builder; nil for a root-level or top-level port
|
|
36
|
+
# @param legacy_bare_port [Boolean] true only for `Hecks.port`: an empty body then builds
|
|
37
|
+
# a verbless `Port` rather than being refused
|
|
32
38
|
def initialize(name, owner: nil, legacy_bare_port: false)
|
|
33
39
|
@name = name
|
|
34
40
|
@owner = owner
|
|
@@ -38,40 +44,63 @@ module Hecks
|
|
|
38
44
|
@legacy_bare_port = legacy_bare_port
|
|
39
45
|
end
|
|
40
46
|
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
47
|
+
# Declares an inbound operation: a fact the outside world delivers to this domain.
|
|
48
|
+
#
|
|
49
|
+
# **What the outside tells us** — an external fact arriving, translated
|
|
50
|
+
# into this domain's own word for it. Spelled `operation` or `tells`;
|
|
51
|
+
# `operation` stays because the corpus is full of it, and renaming
|
|
52
|
+
# a word costs every chapter that uses it for no gain a reader can
|
|
53
|
+
# feel.
|
|
46
54
|
#
|
|
47
|
-
#
|
|
48
|
-
# (slice 4c). `operation`/`tells` are
|
|
55
|
+
# Answers both words — item #13's full metaprogrammed dispatch
|
|
56
|
+
# (slice 4c). `operation`/`tells` are two separate Keyword rows
|
|
49
57
|
# (a word admitting two forms) that both name `calls: "tells_impl"`
|
|
50
|
-
# — the routing between the two spellings
|
|
58
|
+
# — the routing between the two spellings lives in the table,
|
|
51
59
|
# not in a Ruby `alias`. Not bootstrap-reachable (checked
|
|
52
|
-
# directly), so
|
|
60
|
+
# directly), so its `BOOTSTRAP_CALLS_FALLBACK` row is never consulted.
|
|
61
|
+
#
|
|
62
|
+
# @param name [String] the operation's name, such as `"PaymentSettled"`
|
|
63
|
+
# @param to [Symbol, String, Module, nil] the aggregate the operation routes to, written
|
|
64
|
+
# as a bare constant; nil leaves routing to the operation's own attributes
|
|
65
|
+
# @yield the operation body (`attribute`, `emits`), evaluated against a
|
|
66
|
+
# `PortOperationBuilder`
|
|
67
|
+
# @return [Array<Bluebook::PortOperation>] every operation declared so far, this one last
|
|
68
|
+
# @raise [Bluebook::DSL::Malformed] if the body declares no `emits`, or uses `answers` or
|
|
69
|
+
# `refuses`, which belong to an `asks`
|
|
53
70
|
def tells_impl(name, to: nil, &)
|
|
54
71
|
@operations << PortOperationBuilder.build(name, to: to, owner: @owner, direction: :inbound, &)
|
|
55
72
|
end
|
|
56
73
|
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
74
|
+
# Declares an outbound operation: a question this domain puts to the outside world.
|
|
75
|
+
#
|
|
76
|
+
# **What we ask of the outside** — the direction that lets a domain
|
|
77
|
+
# call an adapter, not only be called by one. An `asks` is dispatched
|
|
78
|
+
# like any other port operation, so
|
|
60
79
|
# a `policy` can trigger it off an event, and it comes back as one of
|
|
61
80
|
# the two events it named — which is what makes the outside world
|
|
62
81
|
# something the model can reason about rather than a place exceptions
|
|
63
82
|
# come from.
|
|
64
83
|
#
|
|
65
|
-
#
|
|
66
|
-
# (slice 4c), same reasoning as
|
|
84
|
+
# Answers the `asks` word through the table's `calls:` column — item
|
|
85
|
+
# #13's full metaprogrammed dispatch (slice 4c), same reasoning as
|
|
86
|
+
# `tells_impl` above.
|
|
87
|
+
#
|
|
88
|
+
# @param name [String] the operation's name
|
|
89
|
+
# @param to [Symbol, String, Module, nil] the aggregate the operation routes to, written
|
|
90
|
+
# as a bare constant; nil leaves routing to the operation's own attributes
|
|
91
|
+
# @yield the operation body (`attribute`, `answers`, `refuses`), evaluated against a
|
|
92
|
+
# `PortOperationBuilder`
|
|
93
|
+
# @return [Array<Bluebook::PortOperation>] every operation declared so far, this one last
|
|
94
|
+
# @raise [Bluebook::DSL::Malformed] if the body declares `emits`, or lacks either
|
|
95
|
+
# `answers` or `refuses`
|
|
67
96
|
def asks_impl(name, to: nil, &)
|
|
68
97
|
@operations << PortOperationBuilder.build(name, to: to, owner: @owner, direction: :outbound, &)
|
|
69
98
|
end
|
|
70
99
|
|
|
71
|
-
#
|
|
100
|
+
# The driven half of the same word. `operation`/`emits` translates an
|
|
72
101
|
# inbound fact into this domain's own event vocabulary — there is no
|
|
73
102
|
# channel back to a caller beyond the events it emits. `verb` is the
|
|
74
|
-
# opposite direction: the domain calling
|
|
103
|
+
# opposite direction: the domain calling out to a swappable adapter
|
|
75
104
|
# and getting a real value back (a checkout URL, a fetched document),
|
|
76
105
|
# exactly what `Hecks.port "name" do verb "x" end` already builds —
|
|
77
106
|
# this is that same `Port`, reached from the same `port` call
|
|
@@ -83,9 +112,12 @@ module Hecks
|
|
|
83
112
|
# coerce-and-assign with nothing else, now executed by
|
|
84
113
|
# `GenericDispatch`.
|
|
85
114
|
|
|
115
|
+
# Names the verb aggregates call this port by, which makes it a driven `Port` rather than
|
|
116
|
+
# a `DomainPort` of operations.
|
|
117
|
+
#
|
|
86
118
|
# `Hecks.port "x" do verb "y"; signal :effect end`'s own two words,
|
|
87
119
|
# reachable here too — a bare-verb `DomainPortBuilder.build` falls
|
|
88
|
-
# back to the
|
|
120
|
+
# back to the same `Port` object `PortBuilder` produces (`build`,
|
|
89
121
|
# below), so any `.port` file can migrate to being parsed by this
|
|
90
122
|
# builder with zero change to its own text, or to any caller that
|
|
91
123
|
# reads `.verb`/`.signal` off the `Port` it gets back. Ordinary
|
|
@@ -93,20 +125,40 @@ module Hecks
|
|
|
93
125
|
# header is explicit that a word answered this way never reaches
|
|
94
126
|
# its `method_missing`, so no new self-hosted grammar row is
|
|
95
127
|
# needed for either word under this context.
|
|
128
|
+
#
|
|
129
|
+
# @param value [String, Symbol] the verb, such as `"charged_by"`
|
|
130
|
+
# @return [String] the verb as stored
|
|
96
131
|
def verb(value) = @verb = value.to_s
|
|
132
|
+
|
|
133
|
+
# Sets whether a verb-shaped port hands a value back; one left unset signals `:reply`.
|
|
134
|
+
#
|
|
135
|
+
# @param value [Symbol, String] `:reply` when the adapter answers with a value,
|
|
136
|
+
# `:effect` when it is called only for its effect
|
|
137
|
+
# @return [Symbol] the signal as stored
|
|
97
138
|
def signal(value) = @signal = value.to_sym
|
|
98
139
|
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
#
|
|
102
|
-
#
|
|
140
|
+
# Declares one method an adapter bound to a verb-shaped port must respond to.
|
|
141
|
+
#
|
|
142
|
+
# **The method contract** — `PortBuilder#answers`'s own twin: a
|
|
143
|
+
# `.port` file parsed through this builder (the repoint
|
|
144
|
+
# `lib/hecks.rb#port`'s own comment describes) can declare one
|
|
145
|
+
# (`extraction.port`'s own
|
|
103
146
|
# `answers :canonical`, real, live corpus text) — this builder's
|
|
104
147
|
# bare-verb fallback needs to carry it through to the same `Port`
|
|
105
148
|
# object `PortBuilder` itself would have built, or the migration
|
|
106
149
|
# would silently drop a method-contract check for any `.port`
|
|
107
150
|
# file that uses this word.
|
|
151
|
+
#
|
|
152
|
+
# @param name [Symbol, String] the method name, such as `:canonical`
|
|
153
|
+
# @return [Array<Symbol>] every method declared so far, this one last
|
|
108
154
|
def answers(name) = @answers << name.to_sym
|
|
109
155
|
|
|
156
|
+
# Assembles whichever of the two port shapes the body declared.
|
|
157
|
+
#
|
|
158
|
+
# @return [Bluebook::Port, Bluebook::DomainPort] a `Port` when the body named a `verb`
|
|
159
|
+
# (or was empty under `legacy_bare_port:`), otherwise a `DomainPort` of its operations
|
|
160
|
+
# @raise [Bluebook::DSL::Malformed] if the body declares both a verb and operations,
|
|
161
|
+
# declares neither without `legacy_bare_port:`, or the port language refuses the `Port`
|
|
110
162
|
def build
|
|
111
163
|
if @verb && !@operations.empty?
|
|
112
164
|
raise Malformed,
|
|
@@ -123,6 +175,19 @@ module Hecks
|
|
|
123
175
|
DomainPort.new(name: @name, operations: @operations)
|
|
124
176
|
end
|
|
125
177
|
|
|
178
|
+
# Evaluates a `port` block against a fresh builder and returns whichever shape it declared.
|
|
179
|
+
#
|
|
180
|
+
# @param name [String] the port's name
|
|
181
|
+
# @param owner [String, nil] name of the aggregate the port is declared on, or nil for a
|
|
182
|
+
# root-level or top-level port
|
|
183
|
+
# @param legacy_bare_port [Boolean] true only for `Hecks.port`, which lets an empty body
|
|
184
|
+
# build a verbless `Port`
|
|
185
|
+
# @yield the port body, evaluated with the builder as `self`; may be omitted
|
|
186
|
+
# @return [Bluebook::Port, Bluebook::DomainPort] a verb-shaped `Port`, or a `DomainPort`
|
|
187
|
+
# holding the declared operations
|
|
188
|
+
# @raise [Bluebook::DSL::Malformed] if the body declares both shapes, declares neither
|
|
189
|
+
# without `legacy_bare_port:`, holds an operation its builder refuses, or uses a word
|
|
190
|
+
# the `DomainPort` grammar does not admit
|
|
126
191
|
def self.build(name, owner: nil, legacy_bare_port: false, &block)
|
|
127
192
|
builder = new(name, owner: owner, legacy_bare_port: legacy_bare_port)
|
|
128
193
|
builder.instance_eval(&block) if block
|