hecks 1.3.0 → 1.4.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 +7 -7
- data/lib/hecks/adapters/driven/d1.rb +187 -23
- data/lib/hecks/adapters/driven/folder.rb +10 -10
- data/lib/hecks/adapters/driven/google_authentication.rb +8 -8
- data/lib/hecks/adapters/driven/governance_authorization.rb +31 -13
- data/lib/hecks/adapters/driven/heki/journal.rb +5 -4
- data/lib/hecks/adapters/driven/heki/saga_store.rb +5 -5
- data/lib/hecks/adapters/driven/heki.rb +13 -7
- data/lib/hecks/adapters/driven/identity_registry.rb +2 -2
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +3 -3
- data/lib/hecks/adapters/driven/lambda/client.rb +34 -9
- data/lib/hecks/adapters/driven/lambda.rb +39 -33
- data/lib/hecks/adapters/driven/local_storage.rb +17 -10
- data/lib/hecks/adapters/driven/memory.rb +205 -9
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +1 -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 +4 -4
- 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.rb +4 -4
- data/lib/hecks/adapters/driving/github_webhook.rb +18 -18
- data/lib/hecks/behaviors/dsl.rb +2 -2
- data/lib/hecks/behaviors/expectations.rb +23 -23
- data/lib/hecks/behaviors/ir.rb +1 -1
- data/lib/hecks/behaviors/rspec.rb +1 -1
- data/lib/hecks/behaviors/runner.rb +2 -2
- data/lib/hecks/behaviors.rb +1 -1
- data/lib/hecks/bluebook/aggregate.rb +13 -13
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +10 -10
- data/lib/hecks/bluebook/assembly/build.rb +1 -1
- data/lib/hecks/bluebook/assembly/contract.rb +39 -16
- data/lib/hecks/bluebook/assembly/contracts.rb +40 -38
- data/lib/hecks/bluebook/assembly/marks.rb +18 -18
- data/lib/hecks/bluebook/assembly/specializer.rb +19 -21
- data/lib/hecks/bluebook/assembly.rb +9 -9
- data/lib/hecks/bluebook/attribute.rb +9 -9
- data/lib/hecks/bluebook/behaviour/aggregate.rb +11 -11
- data/lib/hecks/bluebook/behaviour/attribute.rb +5 -5
- data/lib/hecks/bluebook/behaviour/chapter.rb +23 -5
- data/lib/hecks/bluebook/behaviour/command.rb +23 -23
- data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -7
- data/lib/hecks/bluebook/behaviour/entity.rb +8 -8
- data/lib/hecks/bluebook/behaviour/hexagon.rb +4 -4
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +5 -5
- data/lib/hecks/bluebook/behaviour/policy.rb +12 -12
- data/lib/hecks/bluebook/behaviour/process_manager.rb +7 -7
- data/lib/hecks/bluebook/behaviour/query.rb +1 -1
- data/lib/hecks/bluebook/behaviour/read_model.rb +8 -8
- data/lib/hecks/bluebook/behaviour/traits.rb +12 -12
- data/lib/hecks/bluebook/behaviour/value_object.rb +6 -6
- data/lib/hecks/bluebook/capabilities.rb +27 -0
- data/lib/hecks/bluebook/chapter.rb +28 -9
- data/lib/hecks/bluebook/command.rb +12 -12
- data/lib/hecks/bluebook/domain_port.rb +9 -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 +96 -96
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +41 -41
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +22 -2
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +111 -74
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +48 -30
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +103 -103
- 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 +56 -56
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +89 -30
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +17 -17
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
- data/lib/hecks/bluebook/dsl/policy_builder.rb +30 -21
- 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 +35 -35
- data/lib/hecks/bluebook/dsl/query_builder.rb +5 -5
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +34 -34
- data/lib/hecks/bluebook/dsl/rule_reference.rb +41 -39
- data/lib/hecks/bluebook/dsl/translation_builder.rb +9 -9
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +16 -16
- 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 +11 -11
- data/lib/hecks/bluebook/expression/ast_json.rb +20 -20
- data/lib/hecks/bluebook/expression/ast_reader.rb +3 -3
- data/lib/hecks/bluebook/expression/canonical_form.rb +9 -9
- data/lib/hecks/bluebook/expression/evaluator.rb +18 -18
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +18 -18
- data/lib/hecks/bluebook/expression/resolver.rb +60 -62
- data/lib/hecks/bluebook/hexagon.rb +1 -1
- data/lib/hecks/bluebook/lifecycle.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -1
- data/lib/hecks/bluebook/meta_validator/judge.rb +101 -87
- data/lib/hecks/bluebook/meta_validator/plan.rb +39 -39
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -2
- data/lib/hecks/bluebook/meta_validator/readings.rb +43 -43
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +44 -37
- data/lib/hecks/bluebook/meta_validator/shapes.rb +25 -21
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +145 -31
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +6 -6
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +5 -5
- data/lib/hecks/bluebook/meta_validator.rb +70 -70
- data/lib/hecks/bluebook/model_check.rb +170 -84
- data/lib/hecks/bluebook/pattern_subset.rb +9 -9
- data/lib/hecks/bluebook/policy.rb +15 -13
- data/lib/hecks/bluebook/process_manager.rb +14 -14
- data/lib/hecks/bluebook/project_register.rb +6 -6
- data/lib/hecks/bluebook/query.rb +4 -4
- data/lib/hecks/bluebook/read_model.rb +14 -14
- data/lib/hecks/bluebook/reference.rb +8 -8
- data/lib/hecks/bluebook/smoke_test.rb +19 -19
- data/lib/hecks/bluebook/synthesizer.rb +12 -12
- data/lib/hecks/bluebook/translation.rb +4 -4
- data/lib/hecks/bluebook/value_object.rb +6 -6
- data/lib/hecks/bluebook.rb +2 -2
- data/lib/hecks/codemod/legacy_dispatch_args.rb +299 -0
- data/lib/hecks/codemod/legacy_dispatch_recorder.rb +186 -0
- data/lib/hecks/codemod.rb +36 -35
- data/lib/hecks/construct.rb +6 -6
- data/lib/hecks/corpus.rb +317 -0
- data/lib/hecks/deprecation.rb +95 -0
- data/lib/hecks/doc/reference.rb +19 -19
- data/lib/hecks/embryonaut_bluebook.rb +11 -11
- 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 +79 -32
- data/lib/hecks/facade/json_door.rb +106 -25
- data/lib/hecks/facade/surface/aggregate_door.rb +42 -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 +180 -19
- data/lib/hecks/forms/html.rb +51 -7
- data/lib/hecks/forms/index_renderer.rb +14 -2
- data/lib/hecks/forms/params.rb +120 -23
- data/lib/hecks/forms/port_argument.rb +2 -2
- data/lib/hecks/forms/query_form_renderer.rb +2 -2
- data/lib/hecks/forms/record_renderer.rb +2 -2
- data/lib/hecks/forms/record_table.rb +1 -1
- data/lib/hecks/forms/value_object_shape.rb +3 -3
- data/lib/hecks/forms.rb +24 -4
- data/lib/hecks/fqn.rb +1 -1
- data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
- data/lib/hecks/framework.rb +48 -17
- data/lib/hecks/freezer.rb +11 -11
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +90 -90
- data/lib/hecks/fuzzing/combination_miner.rb +119 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +140 -45
- data/lib/hecks/fuzzing/coverage_campaign.rb +118 -0
- data/lib/hecks/fuzzing/differential.rb +158 -0
- data/lib/hecks/fuzzing/domain_generator.rb +694 -0
- data/lib/hecks/fuzzing/era_boundary.rb +37 -18
- data/lib/hecks/fuzzing/form_census.rb +35 -20
- data/lib/hecks/fuzzing/generated_domain_check.rb +95 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +6 -6
- data/lib/hecks/fuzzing/isolated_boot.rb +62 -62
- data/lib/hecks/fuzzing/nondeterministic.rb +67 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +19 -21
- data/lib/hecks/fuzzing/properties/corrections.rb +9 -9
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +154 -49
- data/lib/hecks/fuzzing/properties/guards.rb +42 -42
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +32 -32
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +22 -35
- data/lib/hecks/fuzzing/properties/outbox.rb +24 -24
- data/lib/hecks/fuzzing/properties/querying.rb +17 -17
- data/lib/hecks/fuzzing/properties.rb +64 -40
- data/lib/hecks/fuzzing/qa_settings.rb +152 -0
- data/lib/hecks/fuzzing/replay.rb +114 -114
- data/lib/hecks/fuzzing/rotation_priority.rb +10 -10
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +113 -0
- data/lib/hecks/fuzzing/self_consistency.rb +141 -112
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +35 -35
- 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 +58 -31
- data/lib/hecks/fuzzing/sequence_generator.rb +111 -23
- data/lib/hecks/fuzzing/shrinker.rb +197 -0
- data/lib/hecks/fuzzing/structural_skips.rb +23 -130
- data/lib/hecks/fuzzing/sweep_depth.rb +4 -4
- data/lib/hecks/fuzzing/target_capabilities.rb +49 -18
- data/lib/hecks/fuzzing/value_generator.rb +14 -14
- data/lib/hecks/fuzzing.rb +5 -0
- data/lib/hecks/grammar/evolve.rb +10 -10
- data/lib/hecks/grammar.rb +7 -7
- data/lib/hecks/ir.rb +13 -13
- 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/oidc.json +5 -0
- data/lib/hecks/literal.rb +9 -9
- data/lib/hecks/naming.rb +25 -25
- data/lib/hecks/ports/access_control.rb +58 -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 +53 -11
- data/lib/hecks/ports/clock.rb +42 -23
- data/lib/hecks/ports/extraction.rb +16 -0
- data/lib/hecks/ports/identity_assignment.rb +24 -2
- data/lib/hecks/ports/identity_generation.rb +17 -3
- data/lib/hecks/ports/identity_resolution.rb +18 -1
- 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 +28 -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 +57 -4
- 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 +42 -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 +18 -19
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +5 -5
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +1 -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 +3 -3
- data/lib/hecks/ports/query/ordering.rb +6 -6
- data/lib/hecks/ports/query.rb +35 -0
- data/lib/hecks/projections/bootstrap_table.rb +112 -0
- data/lib/hecks/projections/diagrams.rb +75 -75
- data/lib/hecks/projections/glossary/html.rb +3 -3
- data/lib/hecks/projections/glossary/markdown.rb +3 -3
- data/lib/hecks/projections/glossary/mermaid.rb +1 -1
- data/lib/hecks/projections/glossary/sections.rb +1 -1
- data/lib/hecks/projections/glossary/sentences.rb +5 -5
- data/lib/hecks/projections/glossary.rb +15 -15
- data/lib/hecks/projections/ir.rb +1 -1
- data/lib/hecks/projections/model/deviations.rb +18 -17
- data/lib/hecks/projections/model.rb +25 -21
- data/lib/hecks/projections/oidc.rb +7 -7
- data/lib/hecks/projections/parser_table.rb +5 -5
- data/lib/hecks/projections/reference.rb +3 -3
- data/lib/hecks/projections/rust_vocabulary.rb +443 -0
- data/lib/hecks/projections/shape.rb +2 -2
- data/lib/hecks/projections/statements.rb +11 -11
- data/lib/hecks/projections/vocabulary.rb +9 -9
- data/lib/hecks/projections.rb +5 -3
- data/lib/hecks/projector/cli_projector.rb +29 -29
- data/lib/hecks/projector/docs_projector.rb +13 -13
- data/lib/hecks/projector/exporter.rb +42 -21
- data/lib/hecks/projector/ir_projector.rb +1 -1
- data/lib/hecks/projector/narrate_projector.rb +11 -11
- data/lib/hecks/projector/target.rb +13 -13
- data/lib/hecks/projector.rb +15 -15
- data/lib/hecks/query_ir.rb +47 -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 +57 -13
- 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 +3 -3
- data/lib/hecks/router/namespace_installer.rb +3 -3
- data/lib/hecks/router.rb +1 -1
- data/lib/hecks/runtime/aggregate_lock.rb +11 -11
- data/lib/hecks/runtime/boot_gates.rb +3 -3
- data/lib/hecks/runtime/caller.rb +8 -8
- data/lib/hecks/runtime/capability_graph.rb +2 -2
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +22 -25
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +42 -63
- data/lib/hecks/runtime/command_interpreter.rb +159 -102
- data/lib/hecks/runtime/command_rules/admissibility.rb +69 -69
- data/lib/hecks/runtime/command_rules/arithmetic.rb +137 -91
- 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 +35 -35
- data/lib/hecks/runtime/command_rules.rb +3 -0
- data/lib/hecks/runtime/dependency_planning.rb +11 -11
- data/lib/hecks/runtime/dispatcher.rb +283 -90
- data/lib/hecks/runtime/entity_element.rb +151 -67
- data/lib/hecks/runtime/entity_interpreter.rb +108 -82
- data/lib/hecks/runtime/errors.rb +19 -19
- data/lib/hecks/runtime/event.rb +6 -6
- data/lib/hecks/runtime/identity.rb +22 -22
- data/lib/hecks/runtime/instance.rb +39 -14
- data/lib/hecks/runtime/interpreting.rb +12 -12
- data/lib/hecks/runtime/invocation.rb +276 -0
- data/lib/hecks/runtime/loader.rb +14 -14
- data/lib/hecks/runtime/outbox.rb +23 -23
- data/lib/hecks/runtime/policy_interpreter.rb +54 -54
- data/lib/hecks/runtime/port_operation_interpreter.rb +22 -19
- data/lib/hecks/runtime/query_interpreter.rb +55 -64
- data/lib/hecks/runtime/reaction_invocation.rb +20 -20
- data/lib/hecks/runtime/read_model_interpreter.rb +40 -40
- data/lib/hecks/runtime/rebuild_sweep.rb +4 -4
- data/lib/hecks/runtime/reference_hop.rb +6 -6
- data/lib/hecks/runtime/refusal_wording.rb +92 -115
- data/lib/hecks/runtime/registry/saga_persistence.rb +21 -21
- data/lib/hecks/runtime/registry/verification.rb +36 -26
- data/lib/hecks/runtime/registry.rb +45 -28
- data/lib/hecks/runtime/remote_dispatcher.rb +38 -23
- data/lib/hecks/runtime/routing.rb +10 -153
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +17 -17
- data/lib/hecks/runtime/saga_interpreter.rb +64 -64
- data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
- data/lib/hecks/runtime/tenant_check.rb +9 -9
- data/lib/hecks/runtime/tenant_scope.rb +5 -5
- data/lib/hecks/runtime/value/admission.rb +75 -30
- data/lib/hecks/runtime/value/coercion.rb +318 -127
- data/lib/hecks/runtime/value/entity_list_coercion.rb +34 -34
- data/lib/hecks/runtime/value.rb +21 -21
- data/lib/hecks/runtime.rb +7 -7
- data/lib/hecks/storehouse.rb +64 -64
- data/lib/hecks/version.rb +3 -3
- data/lib/hecks/vocabulary.rb +205 -4
- data/lib/hecks.rb +13 -11
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +11 -11
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +14 -12
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +11 -11
- metadata +22 -2
|
@@ -8,7 +8,7 @@ module Hecks
|
|
|
8
8
|
# (attributes, value objects, entities, commands, queries, policies,
|
|
9
9
|
# invariants, preconditions, projected fields, its lifecycle and
|
|
10
10
|
# identity) and assembling the final `Aggregate` IR in `#build`.
|
|
11
|
-
# `entity`/`command`/`query` only
|
|
11
|
+
# `entity`/`command`/`query` only queue a descriptor during
|
|
12
12
|
# `instance_eval` (`#drain_pending!` builds them, in order, once the
|
|
13
13
|
# whole block has run) so a later-declared piece can still be
|
|
14
14
|
# referenced by an earlier line — see `#drain_pending!`'s own header.
|
|
@@ -34,23 +34,23 @@ module Hecks
|
|
|
34
34
|
@queries = []
|
|
35
35
|
@policies = []
|
|
36
36
|
@reference_targets = []
|
|
37
|
-
#
|
|
38
|
-
# comment.
|
|
37
|
+
# The root of the cross-entity given pool — see `#entity`'s own
|
|
38
|
+
# comment. One hash for the whole aggregate, threaded unchanged
|
|
39
39
|
# into every piece nested under it, however deep.
|
|
40
40
|
@entity_named_givens = {}
|
|
41
|
-
#
|
|
42
|
-
# from `BluebookBuilder#aggregate`, shared with every
|
|
41
|
+
# **One level wider still** — the chapter's own pool, threaded in
|
|
42
|
+
# from `BluebookBuilder#aggregate`, shared with every other
|
|
43
43
|
# aggregate the same chapter builds. See `#given`'s own
|
|
44
44
|
# comment for what this closes.
|
|
45
45
|
@chapter_named_givens = chapter_named_givens
|
|
46
|
-
# A
|
|
46
|
+
# A chapter may be split across files — threaded in the same
|
|
47
47
|
# way as `@chapter_named_givens`, one Array shared chapter-wide.
|
|
48
48
|
# See `#pending_chapter_given`'s own comment for what queues
|
|
49
49
|
# here and `BluebookBuilder#resolve_pending_chapter_givens!`
|
|
50
50
|
# for where it drains.
|
|
51
51
|
@chapter_pending_givens = chapter_pending_givens
|
|
52
|
-
#
|
|
53
|
-
#
|
|
52
|
+
# One level wider still, past the chapter's own aggregate-level
|
|
53
|
+
# pool — the chapter's own entity-scoped pool, threaded from
|
|
54
54
|
# `BluebookBuilder#aggregate_impl` the same way
|
|
55
55
|
# `@chapter_named_givens` is, and passed straight through
|
|
56
56
|
# (unchanged) to every top-level piece this aggregate builds
|
|
@@ -58,7 +58,7 @@ module Hecks
|
|
|
58
58
|
# comment for what this closes.
|
|
59
59
|
@chapter_entity_named_givens = chapter_entity_named_givens
|
|
60
60
|
@chapter_entity_pending_givens = chapter_entity_pending_givens
|
|
61
|
-
#
|
|
61
|
+
# **Deferred construction** — `entity`/`command`/`query` push a
|
|
62
62
|
# pending descriptor here instead of building immediately; see
|
|
63
63
|
# `#drain_pending!`'s own comment for why.
|
|
64
64
|
@pending_entities = []
|
|
@@ -72,13 +72,13 @@ module Hecks
|
|
|
72
72
|
@description = value
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
#
|
|
75
|
+
# Origin, not runtime identity — a concept adopted from a canonical
|
|
76
76
|
# source (§28) names where it came from without that fact ever
|
|
77
77
|
# touching `hecks_fqn`/dispatch. Captured raw, the same way
|
|
78
78
|
# `attribute ..., default: { value: "small" }` captures a literal
|
|
79
79
|
# Hash untouched — no re-parsing, no structure imposed beyond
|
|
80
80
|
# "whatever the author wrote."
|
|
81
|
-
#
|
|
81
|
+
# Renamed from `provenance`/`projects`/`lifecycle`/`entity`/
|
|
82
82
|
# `query`/`policy`/`command` (all below) — item #13's full
|
|
83
83
|
# metaprogrammed dispatch (slice 4c). All bootstrap-reachable
|
|
84
84
|
# (used throughout the core/attached chapters), all in
|
|
@@ -92,15 +92,15 @@ module Hecks
|
|
|
92
92
|
# forward it to `attribute_impl()`/`relationship_attribute`
|
|
93
93
|
# even though those already accept it — closed in the same
|
|
94
94
|
# commit that added this comment (`optional: optional`, below).
|
|
95
|
-
# It was a real gap because an aggregate that can point at
|
|
96
|
-
#
|
|
95
|
+
# It was a real gap because an aggregate that can point at one
|
|
96
|
+
# of several targets (Item's own `personal_list_id`/
|
|
97
97
|
# `camping_list_id`, never both) needs each reference optional
|
|
98
98
|
# on the aggregate's own persisted schema, not just as a
|
|
99
99
|
# command's input — real corpus use:
|
|
100
100
|
# `spec/fixtures/hop_chain.bluebook`'s own `Proposal` aggregate
|
|
101
101
|
# declares `reference_to Engagement, optional: true` at the
|
|
102
102
|
# aggregate head.
|
|
103
|
-
#
|
|
103
|
+
# Renamed from `reference_to` — item #13's full metaprogrammed
|
|
104
104
|
# dispatch (slice 4b). Bootstrap-reachable (every core/attached
|
|
105
105
|
# grammar chapter uses reference_to to describe itself), so also
|
|
106
106
|
# named in GenericDispatch::BOOTSTRAP_CALLS_FALLBACK.
|
|
@@ -111,27 +111,27 @@ module Hecks
|
|
|
111
111
|
as || default_reference_name(target), optional: optional)
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
# A
|
|
114
|
+
# A rule may only read within its own aggregate boundary (S12,
|
|
115
115
|
# ADR 0025 — "Consistency across aggregate boundaries"). A
|
|
116
116
|
# `given`/`ensures`/`invariant` used to reach through a
|
|
117
|
-
# `reference_to` at
|
|
117
|
+
# `reference_to` at rule-evaluation time (`References#
|
|
118
118
|
# dereference`, a live query against another aggregate's own
|
|
119
119
|
# repository, unbounded and inconsistent with the "a rule reads
|
|
120
120
|
# only this record" model everywhere else) — `projects` is what
|
|
121
121
|
# replaces that: `projects :customer_status, from: :"customer.
|
|
122
|
-
# status"` declares that
|
|
123
|
-
# `Customer`'s own `:status`, kept fresh by a
|
|
122
|
+
# status"` declares that this aggregate holds its own copy of
|
|
123
|
+
# `Customer`'s own `:status`, kept fresh by a rebuild sweep
|
|
124
124
|
# (`Runtime::ProjectionRebuild`) rather than read live. A rule
|
|
125
125
|
# then reads `customer_status` the same way it reads any other
|
|
126
126
|
# local field — no dot, no reference walk.
|
|
127
127
|
#
|
|
128
|
-
# `from:`
|
|
129
|
-
# `customer`, the attribute
|
|
128
|
+
# `from:` names the local reference, not the target aggregate —
|
|
129
|
+
# `customer`, the attribute this aggregate's own `reference_to
|
|
130
130
|
# Customer` already minted, not `Customer` the type — so two
|
|
131
131
|
# references to the same aggregate (aliased differently) can
|
|
132
|
-
# each carry their own projection without ambiguity. The
|
|
132
|
+
# each carry their own projection without ambiguity. The target
|
|
133
133
|
# field's own existence cannot be checked here: the target
|
|
134
|
-
# aggregate does not exist yet while
|
|
134
|
+
# aggregate does not exist yet while this one is still being
|
|
135
135
|
# declared (the same reason a query's own hop tail is checked
|
|
136
136
|
# by `BluebookBuilder#validate_query_hops!`, once every
|
|
137
137
|
# aggregate in the chapter is real, not by `AggregateBuilder`
|
|
@@ -151,9 +151,9 @@ module Hecks
|
|
|
151
151
|
remote_field: remote_field.to_sym)
|
|
152
152
|
end
|
|
153
153
|
|
|
154
|
-
# `has_many`/`has_one`/`belongs_to` were
|
|
154
|
+
# `has_many`/`has_one`/`belongs_to` were legacy (ADR 0025,
|
|
155
155
|
# "References") — sugar over `reference_to` that collapsed to an
|
|
156
|
-
# anonymous reference and, for `has_many`,
|
|
156
|
+
# anonymous reference and, for `has_many`, lied (singularised its
|
|
157
157
|
# target and minted one scalar, so `film.backers` read `nil` and
|
|
158
158
|
# never `[]`). Wave 6 (identity-and-relationships arc) un-deprecates
|
|
159
159
|
# all three for real: a relationship word now retains the author's
|
|
@@ -161,11 +161,11 @@ module Hecks
|
|
|
161
161
|
# identities, but no longer collapsed to a bare `reference_to`
|
|
162
162
|
# during assembly. `MetaValidator.shadow_parsing?` still routes to
|
|
163
163
|
# `legacy_has_many`/`legacy_has_one` so frozen era text written
|
|
164
|
-
# under the
|
|
164
|
+
# under the old (lying/collapsing) meaning still parses the way it
|
|
165
165
|
# did when it was written — real, if rare corpus: "Combined corpus
|
|
166
166
|
# uses: one."
|
|
167
167
|
#
|
|
168
|
-
#
|
|
168
|
+
# Renamed from `has_many`/`has_one`/`belongs_to` — item #13's full
|
|
169
169
|
# metaprogrammed dispatch (slice 4). Each Keyword row's own
|
|
170
170
|
# `calls:` names the matching `_impl`; not bootstrap-reachable
|
|
171
171
|
# (no core/attached chapter uses one of these to describe itself),
|
|
@@ -208,26 +208,26 @@ module Hecks
|
|
|
208
208
|
@lifecycle = LifecycleBuilder.build(field, default: default, &)
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
-
# A piece is declared
|
|
211
|
+
# A piece is declared in this aggregate — its owner is stamped by
|
|
212
212
|
# `Aggregate#initialize`, once the aggregate exists. Its own
|
|
213
213
|
# commands were given the piece as their owner when it was declared,
|
|
214
214
|
# so the chain closes as chapter -> aggregate -> entity -> command.
|
|
215
|
-
#
|
|
215
|
+
# Not built here — see `#drain_pending!`'s own comment for why
|
|
216
216
|
# this only queues a descriptor.
|
|
217
217
|
#
|
|
218
|
-
# A
|
|
218
|
+
# A precondition shared across sibling pieces, declared once — one
|
|
219
219
|
# level wider than round 4's own `EntityBuilder#given` (shared
|
|
220
|
-
# across
|
|
221
|
-
#
|
|
220
|
+
# across one piece's own commands): `@entity_named_givens` is the
|
|
221
|
+
# same hash threaded into every piece this aggregate builds, so a
|
|
222
222
|
# piece's own entity-level `given(desc) { block }` write-throughs
|
|
223
|
-
# into it, and any
|
|
224
|
-
# bare, the identical description/canonical, evaluated in
|
|
223
|
+
# into it, and any other piece's own command can reference it back
|
|
224
|
+
# bare, the identical description/canonical, evaluated in its own
|
|
225
225
|
# `parent`-relative context. Real, live corpus this closes:
|
|
226
|
-
# `SafeDepositBox`'s `Visit`/`KeyIssuance` — two
|
|
226
|
+
# `SafeDepositBox`'s `Visit`/`KeyIssuance` — two different pieces
|
|
227
227
|
# under one head, each independently typing `given("customer is
|
|
228
228
|
# active") { parent.customer.status == "active" }` byte for byte,
|
|
229
|
-
# which neither the aggregate's
|
|
230
|
-
#
|
|
229
|
+
# which neither the aggregate's own "customer is active" (a
|
|
230
|
+
# different canonical — bare `customer.status`, not
|
|
231
231
|
# `parent.customer.status`, wrong scope for a piece's own command
|
|
232
232
|
# to evaluate) nor round 4's single-piece `given` could reach.
|
|
233
233
|
def entity_impl(name, &block)
|
|
@@ -244,38 +244,38 @@ module Hecks
|
|
|
244
244
|
@policies << reaction
|
|
245
245
|
end
|
|
246
246
|
|
|
247
|
-
# `builder.closed_sets`
|
|
247
|
+
# `builder.closed_sets` too, not only `builder.build` — a real,
|
|
248
248
|
# previously-unreachable gap this exact fix exposed: a
|
|
249
|
-
# value_object's own
|
|
249
|
+
# value_object's own inline `attribute :x, one_of(...)` (now legal
|
|
250
250
|
# — S3, ADR 0025 removed the wrong-arity collision that used to
|
|
251
251
|
# make this crash before it could ever matter) synthesises its own
|
|
252
|
-
# anonymous value object via the
|
|
252
|
+
# anonymous value object via the same `AttributeCollector#closed_
|
|
253
253
|
# sets` mechanism an aggregate's own attributes already use — and
|
|
254
254
|
# nothing installed it anywhere. `Box.attributes` said `size:
|
|
255
255
|
# "Size"` while no "Size" value object existed in the whole
|
|
256
256
|
# domain: a dangling type name, not a working closed set. Flattened
|
|
257
|
-
# into
|
|
257
|
+
# into this aggregate's own `@value_objects`, the identical move
|
|
258
258
|
# `@value_objects + closed_sets` already makes for the aggregate's
|
|
259
259
|
# own direct attributes (see this file's other 5 call sites).
|
|
260
|
-
# `type` —
|
|
260
|
+
# `type` — the bare shorthand (single-attribute value objects):
|
|
261
261
|
# `value_object :Price, Integer` declares a value object with
|
|
262
|
-
# exactly one attribute,
|
|
262
|
+
# exactly one attribute, named `value`, of that type — pure sugar
|
|
263
263
|
# for `value_object("Price") { attribute :value, Integer }`,
|
|
264
|
-
# routed through the
|
|
264
|
+
# routed through the same `attribute_impl` the block form's own
|
|
265
265
|
# `attribute` line reaches (so the quoted-text-type refusal,
|
|
266
266
|
# `one_of(...)`/`list_of(...)` synthesis, everything an attribute
|
|
267
267
|
# line already does, applies unchanged rather than being
|
|
268
268
|
# re-derived here). The name `value` is not arbitrary: a
|
|
269
|
-
# single-attribute value object is a
|
|
269
|
+
# single-attribute value object is a name for a scalar, not a
|
|
270
270
|
# genuine group ([[feedback_name_the_scalar_field]], `Behaviour::
|
|
271
271
|
# ValueObject#sole_attribute`), and `value` is what the language
|
|
272
|
-
# guarantees
|
|
272
|
+
# guarantees every sole field answers to at runtime regardless of
|
|
273
273
|
# its declared name (`Runtime::Value#method_missing`'s alias) —
|
|
274
274
|
# so the shorthand simply declares it under the canonical name
|
|
275
|
-
# directly. Type
|
|
275
|
+
# directly. Type and block together are refused: the block exists
|
|
276
276
|
# to say what the fields are, and the type just said it — two
|
|
277
277
|
# answers to one question is an authoring error, never a merge.
|
|
278
|
-
#
|
|
278
|
+
# Neither type nor block keeps its historical behavior untouched
|
|
279
279
|
# (an empty attribute list — judged, or not, by the language
|
|
280
280
|
# downstream, the same as before this parameter existed).
|
|
281
281
|
def value_object(name, type = nil, &block)
|
|
@@ -293,37 +293,37 @@ module Hecks
|
|
|
293
293
|
@value_objects.concat(builder.closed_sets)
|
|
294
294
|
end
|
|
295
295
|
|
|
296
|
-
# `from:` —
|
|
296
|
+
# `from:` — lifecycle state becomes a command guard (S10, ADR
|
|
297
297
|
# 0025) — `command "Debit", from: "open"` replaces `given
|
|
298
298
|
# ("account is open") { status == "open" }`, written 35 times
|
|
299
|
-
# in two wordings across the corpus. Checked against
|
|
299
|
+
# in two wordings across the corpus. Checked against this
|
|
300
300
|
# aggregate's own lifecycle field (`Admissibility#enforce_
|
|
301
301
|
# lifecycle_guard`) — never a target state, never a transition:
|
|
302
302
|
# the lifecycle already declares which states exist, so naming
|
|
303
303
|
# the legal ones is checkable against it, where a free-text
|
|
304
304
|
# given could drift out of sync with the state machine and did.
|
|
305
305
|
def command_impl(name, from: nil, &block)
|
|
306
|
-
# The verb is declared
|
|
306
|
+
# The verb is declared on this aggregate — the owner `acts_on` answers
|
|
307
307
|
# with — stamped by `Aggregate#initialize` once the aggregate
|
|
308
|
-
# exists. An
|
|
309
|
-
# at the entity's own declaration.
|
|
308
|
+
# exists. An entity's commands take the entity as their owner instead,
|
|
309
|
+
# at the entity's own declaration. Not built here — see
|
|
310
310
|
# `#drain_pending!`'s own comment for why this only queues a
|
|
311
311
|
# descriptor.
|
|
312
312
|
@pending_commands << [name, from, block]
|
|
313
313
|
end
|
|
314
314
|
|
|
315
|
-
# A
|
|
315
|
+
# A precondition shared across commands, declared once (S10, ADR
|
|
316
316
|
# 0025) — an aggregate-level `given`, block required, stored by
|
|
317
317
|
# its own description rather than appended anywhere: a command
|
|
318
318
|
# names it back (`given("customer is active")`, no block of its
|
|
319
319
|
# own) rather than re-typing the predicate, so there is one
|
|
320
320
|
# description and therefore one refusal message no matter which
|
|
321
|
-
# command a caller hits.
|
|
322
|
-
#
|
|
323
|
-
#
|
|
324
|
-
# aggregate has declared
|
|
321
|
+
# command a caller hits. Declare before the commands that
|
|
322
|
+
# reference it — resolution happens at the referencing command's
|
|
323
|
+
# own build time (`CommandBuilder#given`), against whatever this
|
|
324
|
+
# aggregate has declared so far, the one ordering constraint this
|
|
325
325
|
# word carries that `identified_by`/`attribute` do not.
|
|
326
|
-
#
|
|
326
|
+
# Bare — no block — references a sibling aggregate's own
|
|
327
327
|
# already-declared precondition, one level wider than the
|
|
328
328
|
# existing bare-command-references-its-own-aggregate shape
|
|
329
329
|
# (`CommandBuilder#reference_named_given`): `SafeDepositBox`/
|
|
@@ -333,28 +333,28 @@ module Hecks
|
|
|
333
333
|
# — see `BluebookBuilder#aggregate`'s own comment for how that
|
|
334
334
|
# pool is threaded, and `docs/implemented/resolution-rules/chapter-given.md`
|
|
335
335
|
# for the full algorithm and its known limitations (a bare
|
|
336
|
-
# reference trusts its own author to have verified the
|
|
336
|
+
# reference trusts its own author to have verified the same
|
|
337
337
|
# canonical predicate applies — this mechanism does not, and
|
|
338
338
|
# cannot, check that itself; see that doc for which real corpus
|
|
339
339
|
# cases do and do not qualify).
|
|
340
340
|
#
|
|
341
|
-
# `declared_by:`
|
|
341
|
+
# `declared_by:` disambiguates the same description meaning two
|
|
342
342
|
# genuinely different predicates chapter-wide — real, live:
|
|
343
343
|
# `Account`'s own "customer is active" reads bare
|
|
344
|
-
# `customer.status` (a
|
|
344
|
+
# `customer.status` (a direct `reference_to Customer`); `ATMCard`'s
|
|
345
345
|
# own (shared onward with `CardPayment`/`ExternalTransfer`/
|
|
346
346
|
# `ScheduledPayment`/`Statement`) reads `account.customer.status`
|
|
347
|
-
# (reached
|
|
348
|
-
# genuinely different runtime path, correctly kept as the
|
|
347
|
+
# (reached through `Account`) — the identical business fact, a
|
|
348
|
+
# genuinely different runtime path, correctly kept as the same
|
|
349
349
|
# domain wording rather than invented a second spelling for "the
|
|
350
350
|
# same idea, one more hop away" (S10, ADR 0025's own "one idea,
|
|
351
351
|
# one spelling"). Omit it when the description is unambiguous
|
|
352
|
-
# chapter-wide (the common case, and the
|
|
353
|
-
# before this parameter existed) — required only once a
|
|
352
|
+
# chapter-wide (the common case, and the only case this took
|
|
353
|
+
# before this parameter existed) — required only once a second,
|
|
354
354
|
# textually-different canonical registers under the same
|
|
355
355
|
# description; see `reference_named_chapter_given`'s own
|
|
356
356
|
# ambiguity error for how that surfaces.
|
|
357
|
-
#
|
|
357
|
+
# Renamed from `given` — item #13's full metaprogrammed dispatch
|
|
358
358
|
# (slice 4b), same reasoning as reference_to_impl above:
|
|
359
359
|
# bootstrap-reachable, in BOOTSTRAP_CALLS_FALLBACK.
|
|
360
360
|
def given_impl(description, declared_by: nil, &predicate)
|
|
@@ -363,10 +363,10 @@ module Hecks
|
|
|
363
363
|
named = build_rule(Given, description, predicate, owner_name: @name, word: "given",
|
|
364
364
|
extraction_failure: "its source could not be read, so no other runtime could ever evaluate it")
|
|
365
365
|
@named_givens[description] = named
|
|
366
|
-
#
|
|
366
|
+
# Write-through, first-declared-wins per owner — keyed by
|
|
367
367
|
# [description, this aggregate's own name], not description
|
|
368
|
-
# alone: two
|
|
369
|
-
#
|
|
368
|
+
# alone: two different aggregates independently declaring the
|
|
369
|
+
# same description are two distinct candidates a later bare
|
|
370
370
|
# reference chooses between (via `declared_by:` once there is
|
|
371
371
|
# more than one), never silently merged into one slot the way
|
|
372
372
|
# a bare description-only key would.
|
|
@@ -376,16 +376,16 @@ module Hecks
|
|
|
376
376
|
|
|
377
377
|
private
|
|
378
378
|
|
|
379
|
-
#
|
|
379
|
+
# Primitive 2 (RuleReference#resolve_owner_keyed) — see that
|
|
380
380
|
# method's own comment for the pool shape; the three branches
|
|
381
381
|
# below (exact owner / unambiguous single candidate / ambiguous)
|
|
382
|
-
# are this construct's
|
|
383
|
-
# `declared_by:` only exists here so far.
|
|
382
|
+
# are this construct's own refusal wording, not shared, since
|
|
383
|
+
# `declared_by:` only exists here so far. Unresolved (no
|
|
384
384
|
# candidate yet, or `declared_by:` naming an aggregate that
|
|
385
385
|
# hasn't declared it yet) is no longer a fourth branch that
|
|
386
|
-
# raises
|
|
386
|
+
# raises here — see `#pending_chapter_given`, below, for why:
|
|
387
387
|
# a chapter split across files can genuinely reference a
|
|
388
|
-
# precondition a
|
|
388
|
+
# precondition a later file declares, and "not found among
|
|
389
389
|
# what's loaded so far" cannot tell that apart from "genuinely
|
|
390
390
|
# never declared" until every file has.
|
|
391
391
|
def reference_named_chapter_given(description, declared_by:)
|
|
@@ -411,7 +411,7 @@ module Hecks
|
|
|
411
411
|
@named_givens[description] = named
|
|
412
412
|
end
|
|
413
413
|
|
|
414
|
-
# A
|
|
414
|
+
# A chapter may be split across files — the same reason a query
|
|
415
415
|
# hop's own cross-file target, a correlation key's own emitting
|
|
416
416
|
# command, and an event's own declared shape are all resolved
|
|
417
417
|
# once the whole chapter is assembled rather than refused the
|
|
@@ -419,18 +419,18 @@ module Hecks
|
|
|
419
419
|
# far (`BluebookBuilder.validate_assembled!`'s own comment).
|
|
420
420
|
#
|
|
421
421
|
# Unlike those, though, a chapter-given's resolved value is not
|
|
422
|
-
# a pass/fail check on an already-built IR — it
|
|
422
|
+
# a pass/fail check on an already-built IR — it is part of the
|
|
423
423
|
# referencing aggregate's own IR (`preconditions:` below), built
|
|
424
|
-
# and handed off the moment
|
|
424
|
+
# and handed off the moment this aggregate's own file finishes
|
|
425
425
|
# loading, long before a later file might declare the real
|
|
426
|
-
# thing. So this hands back a
|
|
426
|
+
# thing. So this hands back a placeholder `Given` — embedded
|
|
427
427
|
# exactly where the resolved one would be, by Ruby object
|
|
428
|
-
# reference, in this aggregate's own `preconditions`
|
|
429
|
-
# command in this
|
|
428
|
+
# reference, in this aggregate's own `preconditions` and in any
|
|
429
|
+
# command in this same aggregate that separately bare-references
|
|
430
430
|
# the same description (`CommandBuilder#given`'s own hash-chain
|
|
431
431
|
# read of this aggregate's `@named_givens`, the identical key) —
|
|
432
432
|
# and queues the request in `@chapter_pending_givens`.
|
|
433
|
-
# `BluebookBuilder#resolve_pending_chapter_givens!`
|
|
433
|
+
# `BluebookBuilder#resolve_pending_chapter_givens!` mutates this
|
|
434
434
|
# exact object in place, once every file has loaded, so every
|
|
435
435
|
# existing reference to it (there is only ever the one object,
|
|
436
436
|
# never a copy) sees the resolved fields simultaneously. Safe
|
|
@@ -448,7 +448,7 @@ module Hecks
|
|
|
448
448
|
|
|
449
449
|
public
|
|
450
450
|
|
|
451
|
-
#
|
|
451
|
+
# The aggregate boundary is what an invariant defines (S10, ADR
|
|
452
452
|
# 0025 — "Rules") — checked after every command, before save,
|
|
453
453
|
# the same way a value object's already is
|
|
454
454
|
# (`ValueObjectBuilder#invariant`, whose own shape this mirrors
|
|
@@ -458,7 +458,7 @@ module Hecks
|
|
|
458
458
|
# texts across banking's six balance-moving commands, and the
|
|
459
459
|
# four that only increase it said nothing at all — completeness
|
|
460
460
|
# depended on someone noticing which commands could decrease it.
|
|
461
|
-
#
|
|
461
|
+
# Renamed from `invariant` — item #13's full metaprogrammed
|
|
462
462
|
# dispatch (slice 4b), same reasoning as given_impl above.
|
|
463
463
|
def invariant_impl(description, &predicate)
|
|
464
464
|
@invariants << build_rule(Invariant, description, predicate, owner_name: @name, word: "invariant",
|
|
@@ -493,7 +493,7 @@ module Hecks
|
|
|
493
493
|
provenance: @provenance
|
|
494
494
|
)
|
|
495
495
|
|
|
496
|
-
# After the IR exists, on purpose : a reference is declared
|
|
496
|
+
# After the IR exists, on purpose : a reference is declared in the
|
|
497
497
|
# aggregate, and the aggregate the IR graph knows is `ir`, not the
|
|
498
498
|
# builder.
|
|
499
499
|
stamp_references(ir)
|
|
@@ -511,14 +511,14 @@ module Hecks
|
|
|
511
511
|
|
|
512
512
|
private
|
|
513
513
|
|
|
514
|
-
#
|
|
515
|
-
# immediately,
|
|
514
|
+
# **Deferred construction** — `entity`/`command`/`query` used to build
|
|
515
|
+
# immediately, inline, the moment their own DSL line ran during
|
|
516
516
|
# `instance_eval` — meaning a command's own resolution (`sets
|
|
517
517
|
# :field` importing the owner's own attribute, `given("desc")`
|
|
518
518
|
# referencing an aggregate-level precondition, a query's own
|
|
519
519
|
# positional-param resolution) only ever saw whatever `@entities`/
|
|
520
|
-
# `attributes`/`@named_givens`/`@value_objects` held
|
|
521
|
-
#
|
|
520
|
+
# `attributes`/`@named_givens`/`@value_objects` held as of that
|
|
521
|
+
# exact textual line — never what the aggregate's block would go
|
|
522
522
|
# on to declare after it. Three real, confirmed cases in the
|
|
523
523
|
# self-hosted meta-domain violate the "declare before you
|
|
524
524
|
# reference" convention every other resolution rule relies on
|
|
@@ -526,26 +526,26 @@ module Hecks
|
|
|
526
526
|
# Member/Dispatch — see docs/resolution-rules/
|
|
527
527
|
# implicit-append-fields.md's own "Known limitations").
|
|
528
528
|
#
|
|
529
|
-
# This is the
|
|
530
|
-
#
|
|
529
|
+
# This is the same move `BluebookBuilder` already makes one level
|
|
530
|
+
# up, at the chapter level — build every aggregate first, then run
|
|
531
531
|
# cross-referential validation (`validate_query_hops!`,
|
|
532
532
|
# `validate_projected_fields!`, `validate_no_bidirectional_
|
|
533
533
|
# references!`) once `@aggregates` is fully populated — extended
|
|
534
|
-
# one level down: `entity`/`command`/`query` now only
|
|
534
|
+
# one level down: `entity`/`command`/`query` now only queue a
|
|
535
535
|
# descriptor (`@pending_entities`/`@pending_commands`/
|
|
536
536
|
# `@pending_queries`, each preserving its own declared order),
|
|
537
|
-
# and `#build` drains them here, in this exact order,
|
|
537
|
+
# and `#build` drains them here, in this exact order, before any
|
|
538
538
|
# of the existing `seal_*` validations (which already assume
|
|
539
539
|
# `@commands`/`@entities`/`@queries` are the real, final, built
|
|
540
|
-
# objects) — entities
|
|
540
|
+
# objects) — entities first and fully, since a command's own
|
|
541
541
|
# `sets :list, append: {...}` needs a list's element entity
|
|
542
542
|
# already built (`.attributes` populated) to resolve against, not
|
|
543
543
|
# just named.
|
|
544
544
|
#
|
|
545
545
|
# `attribute`/`value_object`/`identified_by`/`given` (block form)
|
|
546
|
-
# are
|
|
546
|
+
# are not deferred — they still build eagerly during
|
|
547
547
|
# `instance_eval`, unchanged. Nothing reads `@entities`/
|
|
548
|
-
# `@commands`/`@queries` from anywhere
|
|
548
|
+
# `@commands`/`@queries` from anywhere other than `#build` and its
|
|
549
549
|
# own private helpers (checked directly), so nothing else in this
|
|
550
550
|
# file needed to change for this to be safe.
|
|
551
551
|
def drain_pending!
|
|
@@ -583,7 +583,7 @@ module Hecks
|
|
|
583
583
|
@value_objects << value_object
|
|
584
584
|
end
|
|
585
585
|
|
|
586
|
-
#
|
|
586
|
+
# Legacy — see `has_many`/`has_one`/`belongs_to`'s own comment;
|
|
587
587
|
# byte-identical to what those three did before this slice.
|
|
588
588
|
def legacy_has_many(type, as:, optional: false)
|
|
589
589
|
plural = Naming.demodulise(type)
|