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
|
@@ -1,25 +1,28 @@
|
|
|
1
|
+
require "digest"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
|
|
1
4
|
module Hecks
|
|
2
5
|
module Bluebook
|
|
3
6
|
module MetaValidator
|
|
4
|
-
# S14, ADR 0026 —
|
|
5
|
-
#
|
|
7
|
+
# S14, ADR 0026 — dispatches the language's own grammar table into
|
|
8
|
+
# itself, once, so `Keyword`/`Argument`'s own `status` genuinely is a
|
|
6
9
|
# lifecycle — checked at real dispatch time (the same admission/
|
|
7
10
|
# coercion/lifecycle-guard door every other command goes through),
|
|
8
11
|
# not merely declared and never exercised.
|
|
9
12
|
#
|
|
10
|
-
#
|
|
13
|
+
# **The source stays static**. Aggregate-local `KeywordSeed`/
|
|
11
14
|
# `ArgumentSeed` value objects (still hand-written `member` rows —
|
|
12
|
-
# now beside the concepts they spell) are what gets
|
|
13
|
-
# is what turns them into what gets
|
|
15
|
+
# now beside the concepts they spell) are what gets written ; this
|
|
16
|
+
# is what turns them into what gets read. `Judge`/`Reconstruction`
|
|
14
17
|
# already draw exactly this line everywhere else in the meta-domain
|
|
15
|
-
# (a chapter's own
|
|
18
|
+
# (a chapter's own declarations versus what gets dispatched from
|
|
16
19
|
# them) — this runs the same distinction one level further out, for
|
|
17
20
|
# the language's own grammar table.
|
|
18
21
|
#
|
|
19
|
-
# A
|
|
20
|
-
# is reserved for `Judge`'s own bootstrap (dispatching a
|
|
21
|
-
# declarations
|
|
22
|
-
# from this one (dispatching the meta-domain's
|
|
22
|
+
# A dedicated runtime, not `MetaValidator.fresh_runtime`. That one
|
|
23
|
+
# is reserved for `Judge`'s own bootstrap (dispatching a chapter's
|
|
24
|
+
# declarations into the meta-domain's grammar) — a different act
|
|
25
|
+
# from this one (dispatching the meta-domain's own grammar table
|
|
23
26
|
# data into a live "Bluebook" domain instance). Sharing the runtime
|
|
24
27
|
# would let one boot's own repository state leak into the other's.
|
|
25
28
|
#
|
|
@@ -29,7 +32,7 @@ module Hecks
|
|
|
29
32
|
#
|
|
30
33
|
# each row a plain Hash, string values, `status` included — the
|
|
31
34
|
# exact shape `ParserTable`/`syntax_conformance_spec` already read
|
|
32
|
-
# off the
|
|
35
|
+
# off the old closed-set members, so neither consumer had to change
|
|
33
36
|
# what it does with a row, only where the row comes from.
|
|
34
37
|
module SyntaxBoot
|
|
35
38
|
module_function
|
|
@@ -40,21 +43,21 @@ module Hecks
|
|
|
40
43
|
# conformance_spec, bin/reference) should each pay for on every
|
|
41
44
|
# call.
|
|
42
45
|
#
|
|
43
|
-
#
|
|
46
|
+
# Keyed by the grammar registry's own chapter set, not by a
|
|
44
47
|
# "ready" flag. `boot` reads exactly two things: the registry's
|
|
45
48
|
# "Bluebook" chapter (the core seed rows) and every chapter in the
|
|
46
49
|
# registry that `attaches_to` a core context (Paging's rows). So
|
|
47
|
-
# the table is a pure function of which chapter
|
|
50
|
+
# the table is a pure function of which chapter objects the
|
|
48
51
|
# registry holds — and that is the cache key: the same chapters,
|
|
49
52
|
# by identity, mean the same table; a chapter replaced (the
|
|
50
53
|
# fixpoint judge swapping a raw chapter for its assembled self)
|
|
51
54
|
# or added (`load_attached_grammar_into`) means a fresh boot.
|
|
52
55
|
#
|
|
53
|
-
#
|
|
56
|
+
# Why not the earlier `grammar_registry_ready?` guard. That guard
|
|
54
57
|
# was right about the hazard — a snapshot taken mid-build, before
|
|
55
58
|
# Paging attached, would be missing limit/offset/cursor/nulls
|
|
56
59
|
# forever — and wrong about the cost of its cure. It refused to
|
|
57
|
-
# cache
|
|
60
|
+
# cache anything until the whole grammar registry had finished
|
|
58
61
|
# building, calling that window "narrow" and recomputing in it
|
|
59
62
|
# "cheap". Measured (hecks_ai_training, a six-entity chess domain,
|
|
60
63
|
# 2026-08-22): every `word_gate_dispatch` landing in that window
|
|
@@ -69,7 +72,7 @@ module Hecks
|
|
|
69
72
|
# chapter objects, so it invalidates this the same way it always
|
|
70
73
|
# invalidated `grammar_registry_ready?`.
|
|
71
74
|
#
|
|
72
|
-
# `equal?`,
|
|
75
|
+
# `equal?`, not `==`, on the chapters — identity is the fact being
|
|
73
76
|
# tracked. Holding the chapter objects themselves (not their ids)
|
|
74
77
|
# in the key also means a collected chapter can never hand its id
|
|
75
78
|
# to a newcomer behind this cache's back.
|
|
@@ -77,7 +80,12 @@ module Hecks
|
|
|
77
80
|
chapters = MetaValidator.grammar_registry.bluebooks.to_a
|
|
78
81
|
return @call if @call && same_chapters?(@call_chapters, chapters)
|
|
79
82
|
|
|
80
|
-
result =
|
|
83
|
+
result = read_disk_cache(chapters) || begin
|
|
84
|
+
fresh = boot
|
|
85
|
+
write_disk_cache(chapters, fresh)
|
|
86
|
+
fresh
|
|
87
|
+
end
|
|
88
|
+
|
|
81
89
|
@call = result
|
|
82
90
|
@call_chapters = chapters
|
|
83
91
|
result
|
|
@@ -90,14 +98,118 @@ module Hecks
|
|
|
90
98
|
end
|
|
91
99
|
end
|
|
92
100
|
|
|
101
|
+
# Cross-process persistence for the same ~1s-per-build work `call`
|
|
102
|
+
# above already memoizes in-process — this file's own chapter-
|
|
103
|
+
# identity keying only ever helps callers sharing one process (the
|
|
104
|
+
# in-memory fixpoint window, or `bin/reference`'s single run); every
|
|
105
|
+
# fresh process (a `qa_sweep --all` child, a `parallel_rspec`
|
|
106
|
+
# worker, `bin/qa_sweep` itself) pays both real builds again from
|
|
107
|
+
# scratch even when the grammar source hasn't changed at all since
|
|
108
|
+
# the last process that built it.
|
|
109
|
+
#
|
|
110
|
+
# Not a fix for the two-builds-per-process shape — investigated and
|
|
111
|
+
# confirmed genuine, not waste (see this module's own header
|
|
112
|
+
# history: the previous "wait for the whole registry" design cost
|
|
113
|
+
# 42 rebuilds/32s per process precisely because real callers need a
|
|
114
|
+
# correct table mid-bootstrap, before Paging attaches). Both builds
|
|
115
|
+
# still happen once each per process; this only makes each of them
|
|
116
|
+
# a cheap disk read instead of a real ~1s dispatch, once some
|
|
117
|
+
# earlier process has already paid for that exact chapter-set +
|
|
118
|
+
# grammar-content combination.
|
|
119
|
+
#
|
|
120
|
+
# Keyed the same way `same_chapters?` is, translated across process
|
|
121
|
+
# boundaries — chapter *object identity* (what the in-memory cache
|
|
122
|
+
# keys on) means nothing to a different process; chapter *names*,
|
|
123
|
+
# in the same order, do. Combined with a content hash of every
|
|
124
|
+
# grammar file `boot` can read from (`seed_chapters` walks every
|
|
125
|
+
# bluebook the registry holds, so this must cover the core chapters
|
|
126
|
+
# and every attached one, not just "Bluebook" + "Paging") — a
|
|
127
|
+
# source edit anywhere in that set correctly misses the old cache
|
|
128
|
+
# entry rather than silently serving a stale table.
|
|
129
|
+
#
|
|
130
|
+
# Fails toward a real boot, never toward a wrong table — same
|
|
131
|
+
# loud-not-silent discipline this codebase already holds CI to
|
|
132
|
+
# (`postgres_io_relevant_changed`'s own header). A missing file, a
|
|
133
|
+
# corrupt Marshal blob, a permission error, an unwritable `tmp/` —
|
|
134
|
+
# every one of these degrades to "no disk cache today", never to a
|
|
135
|
+
# crash or a served-but-wrong table. `tmp/` is already gitignored
|
|
136
|
+
# for exactly this kind of local, disposable-but-useful-while-it-
|
|
137
|
+
# lasts artifact (`Storehouse::LOG_ROOT`'s own header names the
|
|
138
|
+
# same convention).
|
|
139
|
+
#
|
|
140
|
+
# **Atomic write, not a lock** — `qa_sweep --all` spawns up to 4
|
|
141
|
+
# children at once, any of which could reach a cold cache
|
|
142
|
+
# simultaneously and each compute the identical real boot result
|
|
143
|
+
# for the identical key. Writing to a PID-suffixed temp file and
|
|
144
|
+
# `File.rename`ing it into place (a single atomic syscall on the
|
|
145
|
+
# same filesystem) means a concurrent second writer's rename just
|
|
146
|
+
# overwrites the first with byte-identical content — never a torn
|
|
147
|
+
# or partially-written file a concurrent reader could observe.
|
|
148
|
+
#
|
|
149
|
+
# `HECKS_SYNTAX_BOOT_CACHE=off` — an escape hatch needing no code
|
|
150
|
+
# change, the same shape `Storehouse::BOOT_ROOT`'s own
|
|
151
|
+
# `HECKS_STOREHOUSE_ROOT` override uses, for the day this needs to
|
|
152
|
+
# be ruled out while debugging something else entirely.
|
|
153
|
+
CACHE_DIR = File.expand_path("../../../../tmp/hecks_syntax_boot_cache", __dir__).freeze
|
|
154
|
+
|
|
155
|
+
def disk_cache_enabled? = ENV["HECKS_SYNTAX_BOOT_CACHE"] != "off"
|
|
156
|
+
|
|
157
|
+
def read_disk_cache(chapters)
|
|
158
|
+
return nil unless disk_cache_enabled?
|
|
159
|
+
|
|
160
|
+
path = disk_cache_path(chapters)
|
|
161
|
+
return nil unless File.exist?(path)
|
|
162
|
+
|
|
163
|
+
Marshal.load(File.binread(path)) # rubocop:disable Security/MarshalLoad -- own process-local cache, never external input
|
|
164
|
+
rescue StandardError
|
|
165
|
+
nil
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def write_disk_cache(chapters, result)
|
|
169
|
+
return unless disk_cache_enabled?
|
|
170
|
+
|
|
171
|
+
path = disk_cache_path(chapters)
|
|
172
|
+
FileUtils.mkdir_p(CACHE_DIR)
|
|
173
|
+
tmp_path = "#{path}.#{Process.pid}.tmp"
|
|
174
|
+
File.binwrite(tmp_path, Marshal.dump(result))
|
|
175
|
+
File.rename(tmp_path, path)
|
|
176
|
+
rescue StandardError
|
|
177
|
+
nil
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def disk_cache_path(chapters)
|
|
181
|
+
File.join(CACHE_DIR, "#{disk_cache_key(chapters)}.marshal")
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def disk_cache_key(chapters)
|
|
185
|
+
names = chapters.map { |name, _chapter| name }
|
|
186
|
+
Digest::SHA256.hexdigest("#{names.join(',')}:#{grammar_content_digest}")
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Every file `boot` can possibly read from, via `seed_chapters`
|
|
190
|
+
# walking every bluebook the registry holds — not just "Bluebook"
|
|
191
|
+
# and "Paging" (the two chapters this module's own comments name
|
|
192
|
+
# most often), because World/Hecksagon/any future attached chapter
|
|
193
|
+
# are equally eligible to carry their own `KeywordSeed`/
|
|
194
|
+
# `ArgumentSeed` value object. Coarser than strictly necessary (any
|
|
195
|
+
# one file changing invalidates every cached key, not just the
|
|
196
|
+
# chapter it belongs to) — deliberately, since under-covering this
|
|
197
|
+
# set is a correctness bug (a stale table survives a real grammar
|
|
198
|
+
# edit) and over-covering it is only ever a wasted cache miss.
|
|
199
|
+
def grammar_content_digest
|
|
200
|
+
files = (MetaValidator::GRAMMAR_FILES + MetaValidator::WORLD_GRAMMAR + MetaValidator::HECKSAGON_GRAMMAR +
|
|
201
|
+
Dir.glob(File.join(MetaValidator::ATTACHED_GRAMMAR_DIR, "*.bluebook"))).sort
|
|
202
|
+
Digest::SHA256.hexdigest(files.map { |file| File.read(file) }.join("\0"))
|
|
203
|
+
end
|
|
204
|
+
|
|
93
205
|
def boot
|
|
94
206
|
bluebook = MetaValidator.grammar_registry.bluebook("Bluebook")
|
|
95
207
|
# `MetaValidator.fresh_runtime`, not a brand-new `Runtime::
|
|
96
208
|
# Registry` — the grammar registry's own copy already has
|
|
97
209
|
# "Bluebook" registered (`grammar_registry`'s own boot already
|
|
98
|
-
# ran `registry.add_bluebook`)
|
|
210
|
+
# ran `registry.add_bluebook`) and its adapter ports already
|
|
99
211
|
# loaded ; a standalone registry would need both wired by hand.
|
|
100
|
-
# `fresh_runtime` resets `@repositories` on the
|
|
212
|
+
# `fresh_runtime` resets `@repositories` on the same registry —
|
|
101
213
|
# the identical isolation `Judge.new` already relies on for
|
|
102
214
|
# every real domain it judges, proven safe by every dispatch
|
|
103
215
|
# this session has ever made.
|
|
@@ -119,7 +231,7 @@ module Hecks
|
|
|
119
231
|
{ value: text.to_s }
|
|
120
232
|
end
|
|
121
233
|
|
|
122
|
-
#
|
|
234
|
+
# Absent stays absent. A seed row's own optional columns ("was",
|
|
123
235
|
# "at", "named", ...) are empty strings, not nil — `Literal`/CSV-
|
|
124
236
|
# shaped grammar data has no `nil` to write — so this is the one
|
|
125
237
|
# place that decides "" means "not given" for the purpose of an
|
|
@@ -131,7 +243,7 @@ module Hecks
|
|
|
131
243
|
v(text)
|
|
132
244
|
end
|
|
133
245
|
|
|
134
|
-
# `Syntax.Declare`'s own `reference_to Bluebook` names the
|
|
246
|
+
# `Syntax.Declare`'s own `reference_to Bluebook` names the chapter
|
|
135
247
|
# it belongs to — the same fact every other top-level aggregate's
|
|
136
248
|
# own creating command carries (`ProcessManager.Declare`,
|
|
137
249
|
# `Policy.Declare`, ...). This fresh runtime holds no chapter
|
|
@@ -141,15 +253,17 @@ module Hecks
|
|
|
141
253
|
# by anything this boot does.
|
|
142
254
|
def declare_syntax(runtime, bluebook)
|
|
143
255
|
syntax = bluebook.aggregate("Syntax")
|
|
144
|
-
runtime.dispatch("Bluebook::Bluebook.Declare",
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
256
|
+
runtime.dispatch("Bluebook::Bluebook.Declare",
|
|
257
|
+
with: { name: v(bluebook.hecks_name),
|
|
258
|
+
vision: v("the language's own grammar table, " \
|
|
259
|
+
"dispatched into itself"),
|
|
260
|
+
classification: v("core") })
|
|
261
|
+
runtime.dispatch("Bluebook::Syntax.Declare",
|
|
262
|
+
with: { bluebook: bluebook.hecks_name, name: v(syntax.hecks_name) })
|
|
149
263
|
end
|
|
150
264
|
|
|
151
|
-
# `to: "Syntax"`
|
|
152
|
-
#
|
|
265
|
+
# `to: "Syntax"` names the record already opened by `declare_syntax`
|
|
266
|
+
# above — an append onto an existing aggregate, not a second creation
|
|
153
267
|
# of it. This used to smuggle `name: v("Syntax")` into the payload
|
|
154
268
|
# instead, the pre-routing convention `Judge#appends` (the same
|
|
155
269
|
# append shape, for `ValueObject.Member`/`ProcessManager.Handler`)
|
|
@@ -194,12 +308,12 @@ module Hecks
|
|
|
194
308
|
end
|
|
195
309
|
end
|
|
196
310
|
|
|
197
|
-
#
|
|
311
|
+
# Every aggregate-local table in every loaded language chapter.
|
|
198
312
|
# The table's presence is the registration: no chapter, aggregate,
|
|
199
313
|
# filename, or context catalog is maintained here. This finds the core
|
|
200
314
|
# Bluebook concepts, the sibling artifact languages (World, Hecksagon,
|
|
201
315
|
# Port, Adapter, Translation), and attached sub-languages alike.
|
|
202
|
-
# Concatenated into
|
|
316
|
+
# Concatenated into one sequence because `position` is minted from the
|
|
203
317
|
# walk index and must not collide across concepts.
|
|
204
318
|
def all_rows(bluebook, name)
|
|
205
319
|
seed_chapters(bluebook).flat_map { |chapter| rows(chapter, name) }
|
|
@@ -226,7 +340,7 @@ module Hecks
|
|
|
226
340
|
end
|
|
227
341
|
end
|
|
228
342
|
|
|
229
|
-
# Reads the dispatched result back into the
|
|
343
|
+
# Reads the dispatched result back into the same shape `rows`
|
|
230
344
|
# above hands the seed data in as — plain hashes, string values,
|
|
231
345
|
# `status` included — so `ParserTable`/`syntax_conformance_spec`
|
|
232
346
|
# need not know or care that a real dispatch happened in between.
|
|
@@ -10,7 +10,7 @@ module Hecks
|
|
|
10
10
|
# AdapterJudge already are — its own file, its own door, judged
|
|
11
11
|
# through its own self-hosted language (translation.bluebook)
|
|
12
12
|
# rather than left as plain Ruby structs nothing checks. Walks the
|
|
13
|
-
#
|
|
13
|
+
# whole built translation in one pass — the top-level Declare/
|
|
14
14
|
# Retire commands, then every nested aggregate's own Declare plus
|
|
15
15
|
# one Add* command per rule it carries — the same "one judge, every
|
|
16
16
|
# nested record" shape WorldJudge already gives Wiring. Field names
|
|
@@ -35,9 +35,9 @@ module Hecks
|
|
|
35
35
|
|
|
36
36
|
def args(pairs) = pairs.compact
|
|
37
37
|
|
|
38
|
-
# `Runtime::AlreadyExists` is rescued
|
|
38
|
+
# `Runtime::AlreadyExists` is rescued here but not by World/Port/
|
|
39
39
|
# Adapter's own sibling judges — found live, not by inspection.
|
|
40
|
-
# Those three each judge a
|
|
40
|
+
# Those three each judge a single aggregate per build (Port/Adapter)
|
|
41
41
|
# or a Hash keyed by verb (World's own settings, deduped by
|
|
42
42
|
# construction), so a duplicate-identity Declare can never reach
|
|
43
43
|
# their own runtime. `TranslationBuilder#aggregate` appends every
|
|
@@ -65,13 +65,13 @@ module Hecks
|
|
|
65
65
|
send_to("Translation::Translation.Declare", t.domain,
|
|
66
66
|
with: { domain: v(t.domain), from: v(t.from), to: v(t.to) })
|
|
67
67
|
|
|
68
|
-
# `id:`, computed the
|
|
69
|
-
# to])` — Translation's own identity is
|
|
68
|
+
# `id:`, computed the same way — `Naming.identity([domain, from,
|
|
69
|
+
# to])` — Translation's own identity is composite
|
|
70
70
|
# (`identified_by :domain, :from, :to`), the same reason
|
|
71
71
|
# `Wiring.Set`'s own self-reference dispatch (world.bluebook,
|
|
72
72
|
# `WorldJudge#judge_wiring`) needs a computed `id:` rather than
|
|
73
73
|
# a bare field value — a single-field identity (TranslationAggregate's
|
|
74
|
-
# own `name`) is the
|
|
74
|
+
# own `name`) is the one case where the bare value itself is the
|
|
75
75
|
# id, confirmed live via direct dispatch testing, not assumed.
|
|
76
76
|
translation_id = Naming.identity([t.domain, t.from, t.to])
|
|
77
77
|
Array(t.retired).each do |name|
|
|
@@ -3,7 +3,7 @@ module Hecks
|
|
|
3
3
|
module MetaValidator
|
|
4
4
|
# Offers a built .world to the language that describes worlds.
|
|
5
5
|
#
|
|
6
|
-
# A world is a
|
|
6
|
+
# A world is a sibling of a bluebook — the same domain runs in many of
|
|
7
7
|
# them — so it is judged through its own door, against its own language
|
|
8
8
|
# file, and its settings normalise the same way a mutation's fields do:
|
|
9
9
|
# an open map becomes one Wiring per verb and one Setting row per value.
|
|
@@ -51,14 +51,14 @@ module Hecks
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def judge_wiring(domain, verb, values)
|
|
54
|
-
#
|
|
54
|
+
# The same join the language itself derives. Wiring is
|
|
55
55
|
# `identified_by do world; verb.value end` — `Wiring.Declare`
|
|
56
|
-
# (a creating command) ignores this `id:` entirely and computes its
|
|
56
|
+
# (a creating command) ignores this `id:` entirely and computes its own
|
|
57
57
|
# from `world`/`verb`, so a locally minted "#{domain}.#{verb}" named a
|
|
58
58
|
# record `Wiring.Set` could never find : the id passed here has to be
|
|
59
|
-
# the
|
|
59
|
+
# the same derivation, not a second guess at what it must be.
|
|
60
60
|
id = Naming.identity([domain, verb])
|
|
61
|
-
# `world_ref` is the
|
|
61
|
+
# `world_ref` is the world's id and goes bare, the way every reference
|
|
62
62
|
# does now ; the language gives it that explicit `as:` because `world`
|
|
63
63
|
# beside it is an ordinary text attribute that happens to hold the same
|
|
64
64
|
# string, and stays a value object. The two look alike and are not —
|