hecks 2.8.0 → 3.0.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/exe/hecks +50 -7
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +32 -100
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +10 -32
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
- data/lib/hecks/adapters/driven/postgres.rb +149 -136
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +48 -38
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bench/cli.rb +62 -0
- data/lib/hecks/bench/environment.rb +71 -0
- data/lib/hecks/bench/postgres_probe.rb +30 -0
- data/lib/hecks/bench/report.rb +76 -0
- data/lib/hecks/bench/ruby_runner.rb +93 -0
- data/lib/hecks/bench/run.rb +55 -0
- data/lib/hecks/bench/rust_runner.rb +101 -0
- data/lib/hecks/bench/stats.rb +46 -0
- data/lib/hecks/bench/suite.rb +98 -0
- data/lib/hecks/bench/workload.rb +89 -0
- data/lib/hecks/bench.rb +17 -0
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +16 -50
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +49 -67
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +39 -661
- data/lib/hecks/bluebook/hexagon.rb +18 -33
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +87 -352
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +122 -596
- data/lib/hecks/bluebook/pattern_subset.rb +49 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +27 -51
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +9 -99
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +4 -23
- data/lib/hecks/canonical_json.rb +30 -0
- data/lib/hecks/chapters.rb +102 -0
- data/lib/hecks/cli/behaviors.rb +61 -0
- data/lib/hecks/cli/canonicalise.rb +25 -0
- data/lib/hecks/cli/check_engine_agreement.rb +32 -0
- data/lib/hecks/cli/check_era.rb +88 -0
- data/lib/hecks/cli/console.rb +66 -0
- data/lib/hecks/cli/deploy_template_diff.rb +40 -0
- data/lib/hecks/cli/doc_coverage.rb +32 -0
- data/lib/hecks/cli/document.rb +5 -23
- data/lib/hecks/cli/expression_projection.rb +41 -0
- data/lib/hecks/cli/follow.rb +88 -0
- data/lib/hecks/cli/history.rb +44 -0
- data/lib/hecks/cli/ir.rb +4 -6
- data/lib/hecks/cli/mcp.rb +5 -6
- data/lib/hecks/cli/model_check.rb +24 -88
- data/lib/hecks/cli/pattern_cases.rb +47 -0
- data/lib/hecks/cli/present.rb +39 -0
- data/lib/hecks/cli/project_cli.rb +223 -64
- data/lib/hecks/cli/project_diagrams.rb +4 -10
- data/lib/hecks/cli/project_glossary.rb +44 -0
- data/lib/hecks/cli/reference.rb +46 -0
- data/lib/hecks/cli/refresh_projections.rb +44 -0
- data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
- data/lib/hecks/cli/release.rb +70 -0
- data/lib/hecks/cli/release_gem.rb +59 -0
- data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
- data/lib/hecks/cli/rspec_shard_files.rb +66 -0
- data/lib/hecks/cli/run.rb +15 -61
- data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
- data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
- data/lib/hecks/cli/shape.rb +70 -0
- data/lib/hecks/cli/smoke_http.rb +230 -0
- data/lib/hecks/cli/smoke_test.rb +7 -19
- data/lib/hecks/cli/spec_example.rb +27 -0
- data/lib/hecks/cli/statements.rb +32 -0
- data/lib/hecks/cli/stores.rb +4 -6
- data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
- data/lib/hecks/cli.rb +216 -73
- data/lib/hecks/codemod.rb +324 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/corpus.rb +423 -0
- data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
- data/lib/hecks/deploy/oidc.json +82 -2
- data/lib/hecks/doc/reference.rb +351 -0
- data/lib/hecks/doors/cli_door.rb +196 -0
- data/lib/hecks/doors/cli_runner.rb +297 -0
- data/lib/hecks/{facade → doors}/command_request.rb +14 -34
- data/lib/hecks/doors/handle.rb +206 -0
- data/lib/hecks/doors/json_door.rb +132 -0
- data/lib/hecks/doors/launcher_options.rb +129 -0
- data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
- data/lib/hecks/doors/mcp_door_scope.rb +97 -0
- data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
- data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
- data/lib/hecks/doors/ruby_door.rb +77 -0
- data/lib/hecks/doors.rb +61 -0
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +5 -72
- data/lib/hecks/engine_agreement.rb +156 -0
- data/lib/hecks/facade.rb +23 -51
- data/lib/hecks/forms/app.rb +21 -76
- data/lib/hecks/forms/banking_presentation.rb +50 -0
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +31 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
- data/lib/hecks/fuzzing/combination_miner.rb +86 -0
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
- data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
- data/lib/hecks/fuzzing/differential.rb +156 -0
- data/lib/hecks/fuzzing/domain_generator.rb +615 -0
- data/lib/hecks/fuzzing/era_boundary.rb +71 -0
- data/lib/hecks/fuzzing/form_census.rb +136 -0
- data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
- data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
- data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
- data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
- data/lib/hecks/fuzzing/outside_world.rb +45 -0
- data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
- data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
- data/lib/hecks/fuzzing/properties/guards.rb +190 -0
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
- data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
- data/lib/hecks/fuzzing/properties/querying.rb +175 -0
- data/lib/hecks/fuzzing/properties.rb +162 -0
- data/lib/hecks/fuzzing/qa_settings.rb +123 -0
- data/lib/hecks/fuzzing/replay.rb +505 -0
- data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
- data/lib/hecks/fuzzing/self_consistency.rb +339 -0
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
- data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
- data/lib/hecks/fuzzing/shrinker.rb +166 -0
- data/lib/hecks/fuzzing/structural_skips.rb +33 -0
- data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
- data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
- data/lib/hecks/fuzzing/value_generator.rb +216 -0
- data/lib/hecks/fuzzing.rb +23 -0
- data/lib/hecks/grammar/evolve.rb +336 -0
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
- data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
- data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
- data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
- data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
- data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
- data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
- data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
- data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
- data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
- data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
- data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
- data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
- data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
- data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
- data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
- data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
- data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
- data/lib/hecks/hecks/adapters/git.adapter +7 -0
- data/lib/hecks/hecks/adapters/git.rb +102 -0
- data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
- data/lib/hecks/hecks/adapters/host_http.rb +65 -0
- data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
- data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
- data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
- data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
- data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
- data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
- data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
- data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
- data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
- data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
- data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
- data/lib/hecks/hecks/adapters/local_files.rb +46 -0
- data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
- data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
- data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
- data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
- data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
- data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
- data/lib/hecks/hecks/adapters/shell.adapter +7 -0
- data/lib/hecks/hecks/adapters/shell.rb +49 -0
- data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
- data/lib/hecks/hecks/adapters/terminal.rb +74 -0
- data/lib/hecks/hecks/codebase.behaviors +172 -0
- data/lib/hecks/hecks/codebase.bluebook +2453 -0
- data/lib/hecks/hecks/context_map.hecksagon +13 -0
- data/lib/hecks/hecks/custodian.behaviors +179 -0
- data/lib/hecks/hecks/custodian.bluebook +1847 -0
- data/lib/hecks/hecks/deploy.behaviors +74 -0
- data/lib/hecks/hecks/deploy.world +12 -0
- data/lib/hecks/hecks/environments/memory.world +10 -0
- data/lib/hecks/hecks/governance.world +7 -0
- data/lib/hecks/hecks/hecks.behaviors +62 -0
- data/lib/hecks/hecks/hecks.bluebook +124 -0
- data/lib/hecks/hecks/hecks.hecksagon +390 -0
- data/lib/hecks/hecks/hecks.world +42 -0
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/kernel_capabilities.rb +194 -0
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +19 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
- data/lib/hecks/persistence_legacy_fixture.rb +113 -0
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +47 -108
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projection_files.rb +285 -0
- data/lib/hecks/projections/bootstrap_table.rb +12 -44
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +40 -207
- data/lib/hecks/projections/deploy/lambda.rb +191 -708
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +3 -59
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
- data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +48 -147
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +22 -584
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +16 -43
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +13 -32
- data/lib/hecks/projections/reference.rb +4 -18
- data/lib/hecks/projections/rust_vocabulary.rb +13 -251
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +154 -400
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
- data/lib/hecks/quality_control/adapters/agent.rb +58 -0
- data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
- data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
- data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
- data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
- data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
- data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
- data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
- data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
- data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
- data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
- data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
- data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
- data/lib/hecks/quality_control/cli/child.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
- data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
- data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
- data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
- data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
- data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
- data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
- data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
- data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
- data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
- data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
- data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
- data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
- data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
- data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
- data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
- data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
- data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
- data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
- data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
- data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
- data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
- data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
- data/lib/hecks/query_ir.rb +346 -0
- data/lib/hecks/query_ir_mcp.rb +198 -0
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +5 -8
- data/lib/hecks/release/runner/clean_tree.rb +42 -0
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/console.rb +6 -0
- data/lib/hecks/release/runner/gem_publisher.rb +15 -9
- data/lib/hecks/release/runner/npm_publisher.rb +9 -53
- data/lib/hecks/release/runner/preflight.rb +29 -20
- data/lib/hecks/release/runner/published.rb +8 -26
- data/lib/hecks/release/runner/tagger.rb +31 -23
- data/lib/hecks/release/runner.rb +60 -38
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +15 -39
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/adapter_lookup.rb +124 -0
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
- data/lib/hecks/runtime/command_interpreter.rb +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +50 -104
- data/lib/hecks/runtime/dispatcher.rb +134 -243
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +14 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +109 -194
- data/lib/hecks/runtime/outbox.rb +39 -262
- data/lib/hecks/runtime/policy_interpreter.rb +43 -202
- data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
- data/lib/hecks/runtime/query_interpreter.rb +122 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/reaction_outcome.rb +89 -0
- data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +28 -87
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +213 -227
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +156 -247
- data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +162 -760
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value/field_checks.rb +172 -0
- data/lib/hecks/runtime/value.rb +15 -84
- data/lib/hecks/runtime.rb +35 -69
- data/lib/hecks/rust_build/conformance.rb +158 -0
- data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
- data/lib/hecks/rust_build/coverage.rb +218 -0
- data/lib/hecks/rust_build/native_build.rb +124 -0
- data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
- data/lib/hecks/rust_build/project_rust.rb +332 -0
- data/lib/hecks/rust_build/wasm.rb +105 -0
- data/lib/hecks/rust_build/wasm_browser.rb +113 -0
- data/lib/hecks/rust_build.rb +144 -0
- data/lib/hecks/storehouse.rb +155 -582
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/three_zero/forms.yml +127 -0
- data/lib/hecks/three_zero.rb +12 -0
- data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
- data/lib/hecks/tools/comment_style.rb +1070 -0
- data/lib/hecks/tools/corpus_report.rb +87 -0
- data/lib/hecks/tools/deploy_recipe.rb +255 -0
- data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
- data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
- data/lib/hecks/tools/era_projection_backfill.rb +94 -0
- data/lib/hecks/tools/era_reattest.rb +146 -0
- data/lib/hecks/tools/evolve_run.rb +189 -0
- data/lib/hecks/tools/fuzz_sweep.rb +373 -0
- data/lib/hecks/tools/heki_compaction.rb +100 -0
- data/lib/hecks/tools/hoist_local_givens.rb +246 -0
- data/lib/hecks/tools/journal_compaction.rb +89 -0
- data/lib/hecks/tools/oidc_manifests.rb +70 -0
- data/lib/hecks/tools/query_ir_run.rb +81 -0
- data/lib/hecks/tools/regeneration_run.rb +166 -0
- data/lib/hecks/tools/rust_comment_style.rb +642 -0
- data/lib/hecks/tools/sequence_script.rb +62 -0
- data/lib/hecks/tools/tail_merge.rb +117 -0
- data/lib/hecks/tools/tenant_provisioning.rb +142 -0
- data/lib/hecks/tools/translation_audit.rb +208 -0
- data/lib/hecks/tools/translation_scaffold.rb +131 -0
- data/lib/hecks/tools.rb +86 -0
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks.rb +52 -90
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- data/qa/settings.yml +66 -0
- data/rust/.cargo/config.toml +6 -0
- data/rust/.gitignore +2 -0
- data/rust/Cargo.lock +54 -0
- data/rust/Cargo.toml +61 -0
- data/rust/build/.cargo/config.toml +3 -0
- data/rust/build/.gitignore +1 -0
- data/rust/build/Cargo.lock +7 -0
- data/rust/build/Cargo.toml +19 -0
- data/rust/build/src/build_artifact.rs +47 -0
- data/rust/build/src/cargo_sync.rs +248 -0
- data/rust/build/src/json.rs +421 -0
- data/rust/build/src/lineage_pass.rs +285 -0
- data/rust/build/src/main.rs +51 -0
- data/rust/build/src/optional_pass.rs +150 -0
- data/rust/build/src/pipeline.rs +264 -0
- data/rust/build/src/reserved_names.rs +76 -0
- data/rust/build/src/resolve.rs +124 -0
- data/rust/build/src/root.rs +25 -0
- data/rust/build/src/sidecars.rs +73 -0
- data/rust/build/src/subprocess.rs +51 -0
- data/rust/build/src/tmp.rs +31 -0
- data/rust/codegen/.cargo/config.toml +3 -0
- data/rust/codegen/.gitignore +1 -0
- data/rust/codegen/Cargo.lock +7 -0
- data/rust/codegen/Cargo.toml +20 -0
- data/rust/codegen/src/attr.rs +32 -0
- data/rust/codegen/src/bridging.rs +481 -0
- data/rust/codegen/src/commands.rs +1226 -0
- data/rust/codegen/src/constraints.rs +109 -0
- data/rust/codegen/src/dependency_planning.rs +209 -0
- data/rust/codegen/src/domain_generator.rs +1288 -0
- data/rust/codegen/src/exemplar.rs +230 -0
- data/rust/codegen/src/expr_emitter.rs +87 -0
- data/rust/codegen/src/fielded.rs +192 -0
- data/rust/codegen/src/hecks_naming.rs +33 -0
- data/rust/codegen/src/json.rs +335 -0
- data/rust/codegen/src/json_codec.rs +697 -0
- data/rust/codegen/src/literal.rs +207 -0
- data/rust/codegen/src/main.rs +290 -0
- data/rust/codegen/src/manifest.rs +227 -0
- data/rust/codegen/src/mutations.rs +784 -0
- data/rust/codegen/src/naming.rs +286 -0
- data/rust/codegen/src/ports.rs +208 -0
- data/rust/codegen/src/prelude.rs +116 -0
- data/rust/codegen/src/queries.rs +786 -0
- data/rust/codegen/src/reactions.rs +532 -0
- data/rust/codegen/src/read_models.rs +697 -0
- data/rust/codegen/src/reference_specs.rs +40 -0
- data/rust/codegen/src/registry.rs +966 -0
- data/rust/codegen/src/reserved_names.rs +76 -0
- data/rust/codegen/src/shared.rs +93 -0
- data/rust/codegen/src/skip_reason.rs +25 -0
- data/rust/codegen/src/types.rs +362 -0
- data/rust/host/.cargo/config.toml +3 -0
- data/rust/host/.gitignore +1 -0
- data/rust/host/Cargo.lock +4297 -0
- data/rust/host/Cargo.toml +61 -0
- data/rust/host/HECKS_RELEASE +1 -0
- data/rust/host/rds-ca-bundle.pem +2736 -0
- data/rust/host/src/api.rs +1596 -0
- data/rust/host/src/approval.rs +652 -0
- data/rust/host/src/auth.rs +1287 -0
- data/rust/host/src/bin/expr_harness.rs +46 -0
- data/rust/host/src/bin/lineage_harness.rs +119 -0
- data/rust/host/src/bin/mint_harness.rs +135 -0
- data/rust/host/src/checkout.rs +265 -0
- data/rust/host/src/dispatch.rs +1443 -0
- data/rust/host/src/expr_json.rs +1117 -0
- data/rust/host/src/field_hints.rs +52 -0
- data/rust/host/src/ir.rs +733 -0
- data/rust/host/src/journal.rs +874 -0
- data/rust/host/src/lambda_client.rs +378 -0
- data/rust/host/src/log.rs +147 -0
- data/rust/host/src/main.rs +474 -0
- data/rust/host/src/mint.rs +1865 -0
- data/rust/host/src/payments/keystore.rs +330 -0
- data/rust/host/src/payments/tests.rs +1400 -0
- data/rust/host/src/payments.rs +767 -0
- data/rust/host/src/presentation.rs +698 -0
- data/rust/host/src/presentation_write.rs +1431 -0
- data/rust/host/src/query_step.rs +149 -0
- data/rust/host/src/rate_limit.rs +904 -0
- data/rust/host/src/reference_transform.rs +241 -0
- data/rust/host/src/reference_validate.rs +338 -0
- data/rust/host/src/resend.rs +296 -0
- data/rust/host/src/secrets.rs +106 -0
- data/rust/host/src/server.rs +663 -0
- data/rust/host/src/storage_shape.rs +175 -0
- data/rust/host/src/test_pg.rs +40 -0
- data/rust/host/src/ui_schema.rs +1351 -0
- data/rust/host/src/wasm_runner.rs +191 -0
- data/rust/host/src/web/newsletter/cooldown.rs +126 -0
- data/rust/host/src/web/newsletter/tests.rs +104 -0
- data/rust/host/src/web/newsletter.rs +310 -0
- data/rust/host/src/web/newsletter_send.rs +357 -0
- data/rust/host/src/web/registrations.rs +1505 -0
- data/rust/host/src/web.rs +2937 -0
- data/rust/lsp/.gitignore +1 -0
- data/rust/lsp/Cargo.lock +7 -0
- data/rust/lsp/Cargo.toml +16 -0
- data/rust/lsp/README.md +133 -0
- data/rust/lsp/src/diagnostics.rs +165 -0
- data/rust/lsp/src/json.rs +385 -0
- data/rust/lsp/src/main.rs +399 -0
- data/rust/lsp/src/outline.rs +177 -0
- data/rust/lsp/src/rpc.rs +67 -0
- data/rust/parser/.cargo/config.toml +5 -0
- data/rust/parser/.gitignore +1 -0
- data/rust/parser/Cargo.lock +7 -0
- data/rust/parser/Cargo.toml +21 -0
- data/rust/parser/src/build/closed_sets.rs +27 -0
- data/rust/parser/src/build/identity.rs +276 -0
- data/rust/parser/src/build/mod.rs +12 -0
- data/rust/parser/src/build/naming.rs +141 -0
- data/rust/parser/src/build/pattern_subset.rs +161 -0
- data/rust/parser/src/build/query_derive.rs +72 -0
- data/rust/parser/src/build/query_inference.rs +269 -0
- data/rust/parser/src/build/query_options.rs +100 -0
- data/rust/parser/src/build/read_model.rs +94 -0
- data/rust/parser/src/build/references.rs +32 -0
- data/rust/parser/src/canonical.rs +114 -0
- data/rust/parser/src/diag.rs +55 -0
- data/rust/parser/src/emit.rs +953 -0
- data/rust/parser/src/expr/ast_json.rs +147 -0
- data/rust/parser/src/expr/evaluator.rs +81 -0
- data/rust/parser/src/expr/mod.rs +84 -0
- data/rust/parser/src/expr/resolver.rs +497 -0
- data/rust/parser/src/ir.rs +387 -0
- data/rust/parser/src/keywords.rs +585 -0
- data/rust/parser/src/lex.rs +662 -0
- data/rust/parser/src/main.rs +252 -0
- data/rust/parser/src/parse/aggregate.rs +612 -0
- data/rust/parser/src/parse/chapter.rs +517 -0
- data/rust/parser/src/parse/command.rs +637 -0
- data/rust/parser/src/parse/domain_port.rs +127 -0
- data/rust/parser/src/parse/entity.rs +527 -0
- data/rust/parser/src/parse/file.rs +67 -0
- data/rust/parser/src/parse/hecksagon.rs +231 -0
- data/rust/parser/src/parse/lifecycle.rs +162 -0
- data/rust/parser/src/parse/mod.rs +1262 -0
- data/rust/parser/src/parse/policy.rs +87 -0
- data/rust/parser/src/parse/process_manager.rs +305 -0
- data/rust/parser/src/parse/query.rs +100 -0
- data/rust/parser/src/parse/read_model.rs +214 -0
- data/rust/parser/src/parse/value_object.rs +250 -0
- data/rust/parser/src/ruby_value.rs +422 -0
- data/rust/project/bridging.rb +257 -0
- data/rust/project/commands.rb +877 -0
- data/rust/project/constraints.rb +86 -0
- data/rust/project/dependency_planning.rb +178 -0
- data/rust/project/domain_generator.rb +980 -0
- data/rust/project/exemplar.rb +148 -0
- data/rust/project/expr_emitter.rb +72 -0
- data/rust/project/fielded.rb +141 -0
- data/rust/project/json_codec.rb +641 -0
- data/rust/project/mutations.rb +721 -0
- data/rust/project/naming.rb +205 -0
- data/rust/project/ports.rb +65 -0
- data/rust/project/queries.rb +493 -0
- data/rust/project/reactions.rb +317 -0
- data/rust/project/read_models.rb +690 -0
- data/rust/project/reference_specs.rb +27 -0
- data/rust/project/registry.rb +396 -0
- data/rust/project/skip_reason.rb +29 -0
- data/rust/project/types.rb +225 -0
- data/rust/project/write_if_changed.rb +83 -0
- data/rust/project.rb +30 -0
- data/rust/project_rust_pipeline.rb +383 -0
- data/rust/src/exemplar/commands.rs +279 -0
- data/rust/src/exemplar/constraints.rs +18 -0
- data/rust/src/exemplar/fielded.rs +280 -0
- data/rust/src/exemplar/json.rs +277 -0
- data/rust/src/exemplar/mod.rs +17 -0
- data/rust/src/exemplar/mutations.rs +80 -0
- data/rust/src/exemplar/queries.rs +33 -0
- data/rust/src/exemplar/reactions.rs +88 -0
- data/rust/src/exemplar/read_models.rs +48 -0
- data/rust/src/exemplar/registry.rs +166 -0
- data/rust/src/exemplar/types.rs +44 -0
- data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
- data/rust/src/kernel/attribute_shapes/list.rs +18 -0
- data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
- data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
- data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
- data/rust/src/kernel/cli.rs +585 -0
- data/rust/src/kernel/dispatch.rs +1090 -0
- data/rust/src/kernel/expr.rs +458 -0
- data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
- data/rust/src/kernel/expression_operators/comparison.rs +48 -0
- data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
- data/rust/src/kernel/expression_operators/logical.rs +13 -0
- data/rust/src/kernel/expression_operators/membership.rs +18 -0
- data/rust/src/kernel/expression_operators/mod.rs +68 -0
- data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
- data/rust/src/kernel/expression_operators/positional.rs +126 -0
- data/rust/src/kernel/expression_operators/presence.rs +101 -0
- data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
- data/rust/src/kernel/expression_operators/sized.rs +35 -0
- data/rust/src/kernel/expression_operators/text.rs +79 -0
- data/rust/src/kernel/expression_operators/to_string.rs +18 -0
- data/rust/src/kernel/json.rs +779 -0
- data/rust/src/kernel/mod.rs +133 -0
- data/rust/src/kernel/named_query.rs +219 -0
- data/rust/src/kernel/orchestrate.rs +1810 -0
- data/rust/src/kernel/pattern.rs +307 -0
- data/rust/src/kernel/query_comparators.rs +206 -0
- data/rust/src/kernel/query_ordering.rs +103 -0
- data/rust/src/kernel/read_model.rs +914 -0
- data/rust/src/kernel/reference_lookup.rs +149 -0
- data/rust/src/kernel/repository.rs +468 -0
- data/rust/src/kernel/routing.rs +612 -0
- data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
- data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
- data/rust/src/kernel/vocab/field_hint.rs +70 -0
- data/rust/src/kernel/vocab/mod.rs +20 -0
- data/rust/src/kernel/vocab/query_comparator.rs +65 -0
- data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
- data/rust/src/lib.rs +8 -0
- data/rust/src/main.rs +16 -0
- data/rust/web/.gitignore +1 -0
- data/rust/web/Cargo.lock +119 -0
- data/rust/web/Cargo.toml +18 -0
- data/rust/web/src/lib.rs +8 -0
- metadata +478 -12
- data/lib/hecks/facade/cli_door.rb +0 -178
- data/lib/hecks/facade/cli_runner.rb +0 -271
- data/lib/hecks/facade/handle.rb +0 -293
- data/lib/hecks/facade/json_door.rb +0 -247
- data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
- data/lib/hecks/facade/surface/chapter.rb +0 -116
- data/lib/hecks/facade/surface.rb +0 -61
- data/lib/hecks/mcp_door_scope.rb +0 -176
|
@@ -8,22 +8,16 @@ require_relative "saga_pending_dispatch"
|
|
|
8
8
|
|
|
9
9
|
module Hecks
|
|
10
10
|
module Runtime
|
|
11
|
-
# Runs one domain's
|
|
12
|
-
#
|
|
13
|
-
# starts_on event, advances a matching handler's state and dispatches
|
|
14
|
-
# its declared commands, and ends/deletes the instance on ends_on —
|
|
15
|
-
# checkpointing each transition durably before its dispatches run.
|
|
11
|
+
# Runs one domain's declared process managers against a just-emitted
|
|
12
|
+
# event, checkpointing each transition durably before its dispatches run.
|
|
16
13
|
class SagaInterpreter
|
|
17
14
|
include Correlation
|
|
18
15
|
|
|
19
|
-
# The trigger lives on the declaration it triggers
|
|
20
|
-
# notices it — see ProcessManager::REFUSED.
|
|
16
|
+
# The trigger lives on the declaration it triggers — see ProcessManager::REFUSED.
|
|
21
17
|
REFUSED = Bluebook::ProcessManager::REFUSED
|
|
22
18
|
|
|
23
|
-
# A crash gets this many
|
|
24
|
-
#
|
|
25
|
-
# `deliver_saga_dispatch`'s own comment for why a crash isn't unwound
|
|
26
|
-
# on the first failure the way a domain refusal is.
|
|
19
|
+
# A crash gets this many retries before it's treated as something to
|
|
20
|
+
# compensate for, instead of unwinding on the first failure.
|
|
27
21
|
MAX_DEFECT_RETRIES = 3
|
|
28
22
|
|
|
29
23
|
attr_reader :registry
|
|
@@ -38,12 +32,7 @@ module Hecks
|
|
|
38
32
|
end
|
|
39
33
|
|
|
40
34
|
# Runs `domain`'s declared process managers against `event`: begins,
|
|
41
|
-
# advances or ends each matching saga instance
|
|
42
|
-
# before its own dispatches run.
|
|
43
|
-
#
|
|
44
|
-
# `only:` — one process manager, the outbox relay's way of running
|
|
45
|
-
# exactly the consumer a row names (`Runtime::Outbox::Relay#
|
|
46
|
-
# run_consumer`); nil advances every manager the domain declares.
|
|
35
|
+
# advances or ends each matching saga instance.
|
|
47
36
|
#
|
|
48
37
|
# @param event [Runtime::Event] the just-emitted event to react to
|
|
49
38
|
# @param domain [String, Symbol] the domain whose declared process managers
|
|
@@ -64,27 +53,11 @@ module Hecks
|
|
|
64
53
|
|
|
65
54
|
private
|
|
66
55
|
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# the
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
# reordering a saga's own transition history — worse for the
|
|
73
|
-
# adapters with no locking of their own (Heki) than for Postgres.
|
|
74
|
-
# `deep_copy` guards against a real bug shape (over-freezing a live,
|
|
75
|
-
# still-mutated Hash) — never hand a persistence adapter the same
|
|
76
|
-
# object `advance_saga`/`unwind` go on to mutate in place;
|
|
77
|
-
# round-tripping through JSON is also what guarantees the value is
|
|
78
|
-
# safe for every adapter that itself calls `JSON.generate` on it.
|
|
79
|
-
# `pending:` — see saga_pending_dispatch.rb. Injected into the
|
|
80
|
-
# written copy of memory only, never into `instance[:memory]`
|
|
81
|
-
# itself: every other reader of a live instance's memory
|
|
82
|
-
# (`dispatch_args`'s "opening event memory" scope, the fuzzer's
|
|
83
|
-
# own round-trip/shape checks, `saga_spec.rb`'s exact-equality
|
|
84
|
-
# assertion against a fresh instance's seeded memory) sees exactly
|
|
85
|
-
# what it always did. The marker exists only in the persisted
|
|
86
|
-
# blob, and only for as long as a dispatch cascade is genuinely
|
|
87
|
-
# in flight for this instance.
|
|
56
|
+
# Holds `saga_mutex` across both the in-memory mutation and the
|
|
57
|
+
# persistence write, never just the mutation — otherwise two threads
|
|
58
|
+
# racing the same (process_manager, correlation) key could interleave
|
|
59
|
+
# their writes out of order. `pending:` is injected into the written
|
|
60
|
+
# copy only, never into `instance[:memory]` itself.
|
|
88
61
|
def checkpoint(process_manager, correlation, instance, domain, pending: nil)
|
|
89
62
|
memory = deep_copy(instance[:memory])
|
|
90
63
|
memory[SAGA_PENDING_DISPATCH_KEY] = pending if pending
|
|
@@ -95,13 +68,9 @@ module Hecks
|
|
|
95
68
|
)
|
|
96
69
|
end
|
|
97
70
|
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
#
|
|
101
|
-
# second, parallel `deep_copy_array` reimplementing the same
|
|
102
|
-
# round-trip. `|| []` — an instance from before this field existed
|
|
103
|
-
# (or one that has never completed a compensable leg) rehydrates
|
|
104
|
-
# to an empty ledger, never nil.
|
|
71
|
+
# Wrapped in a Hash before the round-trip since `JSON.parse` only
|
|
72
|
+
# accepts an object at the top level. `|| []` rehydrates a ledger
|
|
73
|
+
# that has never completed a compensable leg to empty, never nil.
|
|
105
74
|
def deep_copy_array(array) = deep_copy(list: array || [])[:list]
|
|
106
75
|
|
|
107
76
|
def deep_copy(hash) = JSON.parse(JSON.generate(hash), symbolize_names: true)
|
|
@@ -119,22 +88,9 @@ module Hecks
|
|
|
119
88
|
created = @registry.saga_mutex.synchronize do
|
|
120
89
|
next false if @registry.saga_instances[process_manager.name].key?(correlation)
|
|
121
90
|
|
|
122
|
-
# `.dup
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
# into over its lifetime (remember-style, growing beyond what
|
|
126
|
-
# the starting event carried) ; the payload it was seeded from
|
|
127
|
-
# is a fact about something that already happened, logged and
|
|
128
|
-
# emitted before the saga ever saw it. Sharing the one Hash
|
|
129
|
-
# object between them means a write into the saga's own memory
|
|
130
|
-
# is silently also a write into an already-emitted event's own
|
|
131
|
-
# payload — retroactively adding a field nothing announced.
|
|
132
|
-
# `event.payload` is deep-frozen by `Event#emit!` by the time
|
|
133
|
-
# this runs, so a naive in-place write here would raise
|
|
134
|
-
# FrozenError rather than corrupt silently — but the `.dup`
|
|
135
|
-
# still matters: it is what makes the saga's own memory a
|
|
136
|
-
# normal, writable Hash of its own, rather than one write away
|
|
137
|
-
# from crashing every future in-place `remember`.
|
|
91
|
+
# `.dup` — a fresh saga's own memory starts as a copy of the
|
|
92
|
+
# starting event's payload, never the frozen payload itself,
|
|
93
|
+
# since memory is written into over the saga's lifetime.
|
|
138
94
|
instance = { state: process_manager.states.first, memory: event.payload.dup, completed_compensations: [] }
|
|
139
95
|
@registry.saga_instances[process_manager.name][correlation] = instance
|
|
140
96
|
checkpoint(process_manager, correlation, instance, domain)
|
|
@@ -146,13 +102,10 @@ module Hecks
|
|
|
146
102
|
instance: correlation, born: true, state: process_manager.states.first }
|
|
147
103
|
end
|
|
148
104
|
|
|
149
|
-
# The mutex covers only the
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
# or itself again) on the same thread, and `Mutex` is not
|
|
154
|
-
# reentrant: holding it across that call would deadlock the
|
|
155
|
-
# thread against itself the moment any real chain did that.
|
|
105
|
+
# The mutex covers only the check-mutate-checkpoint step, never the
|
|
106
|
+
# dispatch cascade that follows — `deliver_saga_dispatch`'s
|
|
107
|
+
# `@door.reenter` can recursively re-enter this interpreter on the
|
|
108
|
+
# same thread, and `Mutex` is not reentrant.
|
|
156
109
|
def advance_saga(process_manager, event, domain)
|
|
157
110
|
return unless process_manager.handles?(event.name)
|
|
158
111
|
|
|
@@ -170,10 +123,9 @@ module Hecks
|
|
|
170
123
|
@registry.saga_log << record.merge(advanced: false, reason: "no conversation remembers #{correlation.inspect}")
|
|
171
124
|
next false
|
|
172
125
|
end
|
|
173
|
-
#
|
|
174
|
-
#
|
|
175
|
-
#
|
|
176
|
-
# answer exactly when their own state is current.
|
|
126
|
+
# Leg chosen by (event, current state) — read under the mutex so
|
|
127
|
+
# two legs on the same event pick based on the state that's
|
|
128
|
+
# actually current right now.
|
|
177
129
|
handler = process_manager.handler_for(event.name, instance[:state])
|
|
178
130
|
unless handler
|
|
179
131
|
@registry.saga_log << record.merge(advanced: false,
|
|
@@ -192,8 +144,6 @@ module Hecks
|
|
|
192
144
|
settle_transition(process_manager, event, handler, instance, correlation, domain, record, pre_state)
|
|
193
145
|
end
|
|
194
146
|
|
|
195
|
-
# "in X, not Y" — the same wording as before C10.3 when one leg
|
|
196
|
-
# answers the event; every leg's own from: listed when several do.
|
|
197
147
|
def leg_mismatch(process_manager, event_name, state)
|
|
198
148
|
expected = process_manager.handlers_for(event_name).map { |h| h.from_state.inspect }.uniq
|
|
199
149
|
"in #{state.inspect}, not #{expected.join(' or ')}"
|
|
@@ -203,41 +153,19 @@ module Hecks
|
|
|
203
153
|
{ on: event.name, from: from_state, to: to_state, dispatches: handler.dispatches.map(&:command_name) }
|
|
204
154
|
end
|
|
205
155
|
|
|
206
|
-
# The shared tail of `advance_saga` and `unwind
|
|
207
|
-
# mutate
|
|
208
|
-
# per caller: `advance_saga`'s own guard also has to handle "no
|
|
209
|
-
# instance at all", `unwind`'s doesn't), then this: log the real
|
|
210
|
-
# observed transition, run the leg's dispatches, and clear the
|
|
211
|
-
# pending marker once that cascade — however it ended — is done.
|
|
156
|
+
# The shared tail of `advance_saga` and `unwind`, both of which guard,
|
|
157
|
+
# mutate and checkpoint under the mutex before calling this.
|
|
212
158
|
def settle_transition(process_manager, event, handler, instance, correlation, domain, record, pre_state,
|
|
213
159
|
drain_compensations: false)
|
|
214
|
-
#
|
|
215
|
-
#
|
|
216
|
-
#
|
|
217
|
-
#
|
|
218
|
-
# its own "declared edges" list from this same handler object (via
|
|
219
|
-
# `process_manager.handlers`), so a log entry that just echoed `handler.
|
|
220
|
-
# from_state`/`handler.to_state` back could never disagree with
|
|
221
|
-
# that list no matter what the runtime actually did — the entry
|
|
222
|
-
# and the thing it's checked against would be the identical fact,
|
|
223
|
-
# read twice. Logging the instance's own observed state instead
|
|
224
|
-
# means a future defect that moves an instance somewhere its own
|
|
225
|
-
# declared handler didn't say (a stale handler reference, the
|
|
226
|
-
# wrong handler picked, a second racing mutation) shows up as a
|
|
227
|
-
# real mismatch instead of vanishing into a tautology.
|
|
160
|
+
# from:/to: read back from `instance` itself, never re-derived from
|
|
161
|
+
# `handler.from_state`/`to_state` — otherwise a log entry checked
|
|
162
|
+
# against that same handler object could never actually disagree
|
|
163
|
+
# with it, no matter what the runtime did.
|
|
228
164
|
@registry.saga_log << record.merge(advanced: true, from: pre_state, to: instance[:state])
|
|
229
165
|
|
|
230
|
-
#
|
|
231
|
-
#
|
|
232
|
-
#
|
|
233
|
-
# and dispatched in reverse completion order, before any
|
|
234
|
-
# hand-written `on :refused` dispatches below — coexistence, not
|
|
235
|
-
# replacement. Drained (not just read) as it fires: a saga's own
|
|
236
|
-
# `on :refused` handler is guarded against re-entry by `unwind`'s
|
|
237
|
-
# own `instance[:state] == handler.from_state` check, so this can
|
|
238
|
-
# only ever run once per refusal — but draining rather than
|
|
239
|
-
# leaving the ledger populated is what makes that true by
|
|
240
|
-
# construction too, not only by the state guard.
|
|
166
|
+
# Derived compensations run newest-first, before any hand-written
|
|
167
|
+
# `on :refused` dispatches below. Drained (popped), not just read —
|
|
168
|
+
# that's what keeps a re-entrant `on :refused` from running twice.
|
|
241
169
|
if drain_compensations
|
|
242
170
|
compensations = instance[:completed_compensations] || []
|
|
243
171
|
deliver_derived_compensation(process_manager, compensations.pop, correlation, domain) until compensations.empty?
|
|
@@ -248,23 +176,11 @@ module Hecks
|
|
|
248
176
|
deliver_saga_dispatch(process_manager, spec, event, instance, correlation, domain)
|
|
249
177
|
end
|
|
250
178
|
|
|
251
|
-
#
|
|
252
|
-
#
|
|
253
|
-
#
|
|
254
|
-
#
|
|
255
|
-
#
|
|
256
|
-
# row from the store before this line ever runs. Writing the
|
|
257
|
-
# clear unconditionally would resurrect a legitimately-ended saga
|
|
258
|
-
# — this diff's own first attempt did exactly that, caught by
|
|
259
|
-
# `saga_durability_spec.rb`'s "deletes the checkpoint once a saga
|
|
260
|
-
# genuinely ends" — so this only re-checkpoints when `instance`
|
|
261
|
-
# is still the same object `@saga_instances` holds for this
|
|
262
|
-
# correlation (`.equal?`, not `==`: a fresh saga reborn under the
|
|
263
|
-
# same correlation between then and now is a different instance,
|
|
264
|
-
# and writing this stale one's state onto that one's row would be
|
|
265
|
-
# its own corruption). Under the mutex — dispatching is over by
|
|
266
|
-
# now, so this is not the reentrancy hazard `advance_saga`'s own
|
|
267
|
-
# comment warns about.
|
|
179
|
+
# Guarded by `.equal?` (not `==`): `deliver_saga_dispatch`'s own
|
|
180
|
+
# `reenter` can trigger this correlation's `ends_on` as a nested
|
|
181
|
+
# reaction, deleting this row before this line runs. Clearing
|
|
182
|
+
# unconditionally would resurrect an already-ended saga, or stamp
|
|
183
|
+
# a reborn instance with a stale one's state.
|
|
268
184
|
@registry.saga_mutex.synchronize do
|
|
269
185
|
next unless @registry.saga_instances[process_manager.name][correlation].equal?(instance)
|
|
270
186
|
|
|
@@ -278,15 +194,9 @@ module Hecks
|
|
|
278
194
|
args = dispatch_args(process_manager, spec, event, instance, correlation)
|
|
279
195
|
record = { process_manager: process_manager.name, instance: correlation, dispatch: spec.command_name }
|
|
280
196
|
|
|
281
|
-
#
|
|
282
|
-
#
|
|
283
|
-
#
|
|
284
|
-
# run; this dispatch's own memory, at the moment it actually
|
|
285
|
-
# fired, is a different fact for a saga whose memory keeps
|
|
286
|
-
# changing). `spec.with_spec.empty?` skipped: nothing declared
|
|
287
|
-
# to check, a tautological pass, the same reason a command with
|
|
288
|
-
# no givens/from is skipped by lifecycle_guard_and_given_
|
|
289
|
-
# violations_are_refused.
|
|
197
|
+
# Raw inputs captured alongside the resolved result — never
|
|
198
|
+
# re-derived later from saga_instances, which only ever holds the
|
|
199
|
+
# final memory, not what it was at the moment this dispatch fired.
|
|
290
200
|
unless spec.with_spec.to_a.empty?
|
|
291
201
|
@registry.saga_dispatch_log << { process_manager: process_manager.name, instance: correlation,
|
|
292
202
|
dispatch: spec.command_name,
|
|
@@ -296,16 +206,8 @@ module Hecks
|
|
|
296
206
|
end
|
|
297
207
|
|
|
298
208
|
if @door.reaction_depth_reached?
|
|
299
|
-
#
|
|
300
|
-
#
|
|
301
|
-
# about it: the leg unambiguously did not run, so it unwinds
|
|
302
|
-
# exactly like a refusal instead of stranding the instance for a
|
|
303
|
-
# human to notice. `unwind`'s own state guard (it moves to its
|
|
304
|
-
# `to_state` before its dispatches run) is what keeps this from
|
|
305
|
-
# looping if the ceiling is still in effect when the compensating
|
|
306
|
-
# leg tries to dispatch — that leg's own attempt hits this same
|
|
307
|
-
# branch, calls `unwind` again, and finds the instance already
|
|
308
|
-
# past `from_state`.
|
|
209
|
+
# Not a domain decision, but unambiguous — the leg didn't run, so
|
|
210
|
+
# it unwinds like a refusal rather than stranding the instance.
|
|
309
211
|
@registry.saga_log << record.merge(delivered: false,
|
|
310
212
|
reason: "reaction depth #{@door.max_reaction_depth} reached")
|
|
311
213
|
unwind(process_manager, event, instance, correlation, domain)
|
|
@@ -315,20 +217,12 @@ module Hecks
|
|
|
315
217
|
attempt = 0
|
|
316
218
|
compensation_recorded = false
|
|
317
219
|
begin
|
|
318
|
-
# Recorded before dispatching, not after `@door.reenter`
|
|
319
|
-
#
|
|
320
|
-
#
|
|
321
|
-
#
|
|
322
|
-
#
|
|
323
|
-
#
|
|
324
|
-
# refusal to ever see this leg's own compensation — found
|
|
325
|
-
# live: Settlement's own AccountDebited handler refuses
|
|
326
|
-
# Account.Credit and unwinds from inside Account.Debit's own
|
|
327
|
-
# `reenter` call, so "delivered: true, then record" left the
|
|
328
|
-
# ledger empty at the exact moment it was needed. Popped back
|
|
329
|
-
# off in the rescues below if this leg's own attempt is the
|
|
330
|
-
# one that failed — never left recorded for a refusal that
|
|
331
|
-
# was never this leg's own to compensate.
|
|
220
|
+
# Recorded before dispatching, not after `@door.reenter` returns —
|
|
221
|
+
# reenter can recursively re-enter this interpreter and refuse
|
|
222
|
+
# before ever returning here, and recording only on success would
|
|
223
|
+
# be too late for that nested refusal to see this leg's own
|
|
224
|
+
# compensation. Popped back off in the rescues below if this
|
|
225
|
+
# leg's own attempt is the one that failed.
|
|
332
226
|
if spec.compensates && !compensation_recorded
|
|
333
227
|
resolved = dispatch_args(process_manager, spec.compensates, event, instance, correlation)
|
|
334
228
|
instance[:completed_compensations] << { command_name: spec.compensates.command_name, args: resolved }
|
|
@@ -349,35 +243,18 @@ module Hecks
|
|
|
349
243
|
@registry.saga_log << record.merge(delivered: true)
|
|
350
244
|
rescue *DOMAIN_REFUSALS => e
|
|
351
245
|
unrecord_compensation(instance, correlation, domain, process_manager) if compensation_recorded
|
|
352
|
-
#
|
|
353
|
-
#
|
|
354
|
-
# `unwind`'s own comment for why the procedure runs its
|
|
355
|
-
# compensation here rather than leaving the money (or whatever
|
|
356
|
-
# else a leg moved) sitting out.
|
|
246
|
+
# A refusal by the target is a recorded outcome, and the leg
|
|
247
|
+
# that raised it unwinds and runs its own compensation there.
|
|
357
248
|
@registry.saga_log << record.merge(delivered: false, reason: e.message)
|
|
358
249
|
unwind(process_manager, event, instance, correlation, domain)
|
|
359
250
|
rescue StandardError => e
|
|
360
251
|
unrecord_compensation(instance, correlation, domain, process_manager) if compensation_recorded
|
|
361
252
|
compensation_recorded = false
|
|
362
|
-
#
|
|
363
|
-
#
|
|
364
|
-
#
|
|
365
|
-
#
|
|
366
|
-
#
|
|
367
|
-
#
|
|
368
|
-
# Unlike a refusal, a crash is not a decision the domain made, so
|
|
369
|
-
# it does not unwind on the first failure — MAX_DEFECT_RETRIES
|
|
370
|
-
# gives a transient failure (a DB timeout, a race, a cold start)
|
|
371
|
-
# a chance to clear on its own, retrying the identical dispatch,
|
|
372
|
-
# before this is treated as something to compensate for. Every
|
|
373
|
-
# attempt is recorded distinguishably (`defect: true`, the
|
|
374
|
-
# error's own class); only once retries are exhausted is it
|
|
375
|
-
# warned to STDERR and unwound — tagged `defect_compensated:
|
|
376
|
-
# true` rather than folded into an ordinary refusal's shape, so
|
|
377
|
-
# the log never misrepresents a crash as a decision the domain
|
|
378
|
-
# made. Compensating a genuinely stuck leg beats leaving it for a
|
|
379
|
-
# human to find; misrepresenting *why* it compensated is what the
|
|
380
|
-
# tag is for.
|
|
253
|
+
# Unlike a refusal, a crash isn't a domain decision, so it
|
|
254
|
+
# doesn't unwind on the first failure — MAX_DEFECT_RETRIES lets a
|
|
255
|
+
# transient failure clear on retry. `defect_compensated: true`
|
|
256
|
+
# tags an exhausted retry distinctly, so the log never
|
|
257
|
+
# misrepresents a crash as a decision the domain made.
|
|
381
258
|
attempt += 1
|
|
382
259
|
if attempt <= MAX_DEFECT_RETRIES
|
|
383
260
|
@registry.saga_log << record.merge(delivered: false, reason: e.message,
|
|
@@ -395,38 +272,23 @@ module Hecks
|
|
|
395
272
|
end
|
|
396
273
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
397
274
|
|
|
398
|
-
#
|
|
399
|
-
#
|
|
400
|
-
#
|
|
401
|
-
# so whatever was just pushed for it was never actually earned.
|
|
402
|
-
# `.pop`, not a search-and-delete: nothing else can have pushed
|
|
403
|
-
# after this leg's own entry without this leg's own `@door.
|
|
404
|
-
# reenter` call having already returned (the recursive re-entry
|
|
405
|
-
# this whole mechanism exists for only ever runs between this
|
|
406
|
-
# push and this leg's own return, and a nested refusal that
|
|
407
|
-
# consumed it already popped it itself — this rollback only ever
|
|
408
|
-
# runs for this leg's own, still-present entry).
|
|
275
|
+
# `.pop`, not search-and-delete — nothing else can have pushed after
|
|
276
|
+
# this leg's own entry without this leg's own `reenter` having
|
|
277
|
+
# already returned first.
|
|
409
278
|
def unrecord_compensation(instance, correlation, domain, process_manager)
|
|
410
279
|
instance[:completed_compensations].pop
|
|
411
280
|
checkpoint(process_manager, correlation, instance, domain)
|
|
412
281
|
end
|
|
413
282
|
|
|
414
|
-
# A refused leg unwinds
|
|
415
|
-
#
|
|
416
|
-
# reaction-depth ceiling
|
|
417
|
-
#
|
|
418
|
-
# comments for why each of those is safe to route here.
|
|
419
|
-
#
|
|
420
|
-
# Until this existed a refusal was recorded and nothing else happened. The
|
|
421
|
-
# wire's thousand was taken from the source, refused by the destination, and
|
|
422
|
-
# sat nowhere until a human dispatched the reversal by hand ; banking's
|
|
423
|
-
# settlement left a debit standing with no credit and no compensation at all.
|
|
424
|
-
# Both bluebooks had written the compensating leg. Nothing armed it.
|
|
283
|
+
# A refused leg unwinds by running its own declared `on :refused`
|
|
284
|
+
# handler, where compensation lives — also the destination for a
|
|
285
|
+
# leg that hit the reaction-depth ceiling or exhausted its defect
|
|
286
|
+
# retries.
|
|
425
287
|
#
|
|
426
|
-
# A compensation that is itself refused does not unwind again
|
|
427
|
-
#
|
|
428
|
-
#
|
|
429
|
-
# from_state and records that instead.
|
|
288
|
+
# A compensation that is itself refused does not unwind again: the
|
|
289
|
+
# state moves to the compensating leg's to_state before its
|
|
290
|
+
# dispatches run, so a second refusal finds the instance already
|
|
291
|
+
# out of from_state and records that instead.
|
|
430
292
|
def unwind(process_manager, event, instance, correlation, domain)
|
|
431
293
|
return unless instance && process_manager.handles?(REFUSED)
|
|
432
294
|
|
|
@@ -435,10 +297,8 @@ module Hecks
|
|
|
435
297
|
pre_state = nil
|
|
436
298
|
|
|
437
299
|
# Same non-reentrancy reasoning as `advance_saga`'s own comment —
|
|
438
|
-
# the mutex covers only the check-
|
|
300
|
+
# the mutex covers only the check-mutate-checkpoint step.
|
|
439
301
|
advanced = @registry.saga_mutex.synchronize do
|
|
440
|
-
# The compensating leg is selected by (`REFUSED`, current state)
|
|
441
|
-
# too — C10.3, one rule for every leg.
|
|
442
302
|
handler = process_manager.handler_for(REFUSED, instance[:state])
|
|
443
303
|
unless handler
|
|
444
304
|
@registry.saga_log << record.merge(advanced: false,
|
|
@@ -454,28 +314,16 @@ module Hecks
|
|
|
454
314
|
end
|
|
455
315
|
return unless advanced
|
|
456
316
|
|
|
457
|
-
#
|
|
458
|
-
#
|
|
459
|
-
# second read of the same handler object `Properties.saga_
|
|
460
|
-
# advances_follow_declared_handlers` checks this log against.
|
|
461
|
-
# `drain_compensations: true` — only `unwind`'s own call site
|
|
462
|
-
# fires derived compensation; `advance_saga`'s own call never
|
|
463
|
-
# does.
|
|
317
|
+
# `drain_compensations: true` only here — `advance_saga`'s own call
|
|
318
|
+
# never fires derived compensation.
|
|
464
319
|
settle_transition(process_manager, event, handler, instance, correlation, domain, record, pre_state,
|
|
465
320
|
drain_compensations: true)
|
|
466
321
|
end
|
|
467
322
|
|
|
468
|
-
#
|
|
469
|
-
#
|
|
470
|
-
#
|
|
471
|
-
#
|
|
472
|
-
# uses. Never re-enters `unwind` on its own failure — a
|
|
473
|
-
# compensation that itself refuses is a real, pre-existing gap
|
|
474
|
-
# this feature makes visible rather than closes (see this file's
|
|
475
|
-
# own class-level notes); `compensation_failed: true` tags it
|
|
476
|
-
# distinctly in the log instead of recording it identically to an
|
|
477
|
-
# ordinary failed delivery, and every other completed compensation
|
|
478
|
-
# still queued still gets its own attempt.
|
|
323
|
+
# `entry[:args]` is already resolved, so this skips `dispatch_args`
|
|
324
|
+
# and goes straight to delivery. Never re-enters `unwind` on its own
|
|
325
|
+
# failure — `compensation_failed: true` tags a refused compensation
|
|
326
|
+
# distinctly rather than as an ordinary failed delivery.
|
|
479
327
|
def deliver_derived_compensation(process_manager, entry, correlation, domain)
|
|
480
328
|
record = { process_manager: process_manager.name, instance: correlation, dispatch: entry[:command_name] }
|
|
481
329
|
|
|
@@ -520,43 +368,11 @@ module Hecks
|
|
|
520
368
|
)
|
|
521
369
|
end
|
|
522
370
|
|
|
523
|
-
#
|
|
524
|
-
#
|
|
525
|
-
#
|
|
526
|
-
#
|
|
527
|
-
#
|
|
528
|
-
# Debit` -> one `::` survives) apart from a same-domain entity
|
|
529
|
-
# command reference (`Manifest::Slot::Fill` -> one `::` survives
|
|
530
|
-
# too, for an unrelated reason — entity nesting, not a domain
|
|
531
|
-
# qualifier) — both collapse to the identical "one `::` left" shape,
|
|
532
|
-
# and the string alone carries no further signal to split them
|
|
533
|
-
# (confirmed against `Naming.command_ref`'s own rewrite: it only
|
|
534
|
-
# ever strips the last `::`, so the count of what remains is blind
|
|
535
|
-
# to why it's there). Picking the cross-domain reading unconditionally
|
|
536
|
-
# would leave `qa/stress_domains/waybill`'s own `Packing` saga dispatching
|
|
537
|
-
# `Manifest::Slot::Fill` — an entity command in its own domain —
|
|
538
|
-
# unprefixed, so `Naming.split_verb` would read "Manifest" as a domain
|
|
539
|
-
# name instead of this chapter's own aggregate, and the dispatch
|
|
540
|
-
# would fail with `UnknownVerb`, silently recorded as an ordinary
|
|
541
|
-
# domain refusal rather than surfacing as the real bug it is.
|
|
542
|
-
#
|
|
543
|
-
# The fix mirrors `PolicyInterpreter#deliver`'s own mechanism,
|
|
544
|
-
# which never had this bug: a policy's cross-domain target is a
|
|
545
|
-
# separate, explicit field (`Policy#target_domain`, set only by the
|
|
546
|
-
# `across` keyword) — `deliver` unconditionally builds
|
|
547
|
-
# `"#{policy.target_domain || domain}::#{policy.trigger_command}"`,
|
|
548
|
-
# never asking whether `trigger_command` looks already-qualified.
|
|
549
|
-
# A saga's own `dispatch`/`compensates` has no such explicit field
|
|
550
|
-
# and no keyword to set one — and, confirmed against the entire
|
|
551
|
-
# corpus (banking's Onboarding/Settlement/ExternalSettlement,
|
|
552
|
-
# quality_control's BugCiWatch, and this domain's own Packing),
|
|
553
|
-
# no saga anywhere ever dispatches genuinely cross-domain: "every
|
|
554
|
-
# command a saga fires lands inside its own bluebook chapter"
|
|
555
|
-
# (`Projections::Diagrams#saga_diagram`'s own comment, written
|
|
556
|
-
# independently of this fix and still true). So the home domain is
|
|
557
|
-
# the only explicit context a saga dispatch ever has — this applies
|
|
558
|
-
# it the same way `deliver` applies its own default (no `across`)
|
|
559
|
-
# case, without inventing a keyword nothing in the corpus needs.
|
|
371
|
+
# Unconditionally the saga's own home domain, never inferred from
|
|
372
|
+
# `command_name`'s shape — unlike a policy's explicit `target_domain`
|
|
373
|
+
# (set by `across`), a saga's `dispatch`/`compensates` has no such
|
|
374
|
+
# field, and every command a saga fires lands inside its own
|
|
375
|
+
# bluebook chapter.
|
|
560
376
|
def qualified(command_name, domain)
|
|
561
377
|
"#{domain}::#{command_name}"
|
|
562
378
|
end
|
|
@@ -1,48 +1,7 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Runtime
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# scoped, minimal answer to the saga-durability review's item 8 (a
|
|
6
|
-
# durable outbox): a marker that survives exactly the window a crash
|
|
7
|
-
# in `advance_saga`/`unwind` can otherwise hide.
|
|
8
|
-
#
|
|
9
|
-
# **The problem this closes** — `checkpoint` persists a saga's new state
|
|
10
|
-
# before the leg that justifies it (`handler.dispatches`) runs, and
|
|
11
|
-
# deliberately so: the mutex it holds is not reentrant, and a
|
|
12
|
-
# dispatch can re-enter this same interpreter. If the process dies
|
|
13
|
-
# in that window, the store says the transition happened and there
|
|
14
|
-
# is no record that its dispatch(es) never ran — not a refusal (the
|
|
15
|
-
# domain never got asked), not a defect (nothing raised), just
|
|
16
|
-
# silence indistinguishable from a leg that finished cleanly.
|
|
17
|
-
#
|
|
18
|
-
# **The fix** — `checkpoint` now writes this key into the same already-
|
|
19
|
-
# durable `memory` blob (no new column, no adapter/schema change:
|
|
20
|
-
# `memory` is already an opaque, adapter-agnostic JSON blob every
|
|
21
|
-
# `save_saga` implementation round-trips verbatim) whenever it
|
|
22
|
-
# checkpoints a state a dispatch cascade hasn't run for yet, and
|
|
23
|
-
# clears it (a second checkpoint, `pending: nil`) once that cascade
|
|
24
|
-
# — success, refusal-compensated, defect-compensated, or ceiling-
|
|
25
|
-
# compensated — has actually run. A crash between those two writes
|
|
26
|
-
# leaves the marker standing; `rehydrate_sagas!` strips it back out
|
|
27
|
-
# of the live instance's own `:memory` (so no dispatch/`given`/
|
|
28
|
-
# fuzzer/doc consumer of a saga's memory ever sees this key — it
|
|
29
|
-
# exists only in the persisted blob) and surfaces it loudly instead.
|
|
30
|
-
#
|
|
31
|
-
# **What this deliberately does not do** — auto-redrive the pending leg.
|
|
32
|
-
# Redelivering a dispatch whose outcome is genuinely unknown is only
|
|
33
|
-
# safe with idempotent delivery (the downstream command recognizing
|
|
34
|
-
# and no-op'ing a duplicate), which hecks's command/event pipeline
|
|
35
|
-
# has no mechanism for today. Blindly re-dispatching without that is
|
|
36
|
-
# how a stalled transfer becomes a double-credited one — a strictly
|
|
37
|
-
# worse defect than the stall it would replace. So this is real,
|
|
38
|
-
# durable, crash-surviving visibility into exactly what a stalled
|
|
39
|
-
# saga was doing when the process died — the missing half of "no
|
|
40
|
-
# reconciliation pass exists". The full pending → claimed →
|
|
41
|
-
# delivered outbox now exists too (`Runtime::Outbox`, ADR 0053) and
|
|
42
|
-
# is complementary, not a replacement: the outbox row names the
|
|
43
|
-
# event owed to this saga (and redrives it if the saga never got to
|
|
44
|
-
# claim it); this marker names the saga's own leg mid-flight after
|
|
45
|
-
# the event was delivered. A crash can leave either standing.
|
|
3
|
+
# Marks a checkpointed saga leg whose dispatch may not have run (persisted in `memory`).
|
|
4
|
+
# Reported, never redriven: dispatch isn't idempotent, so a replay could double-apply.
|
|
46
5
|
SAGA_PENDING_DISPATCH_KEY = :__hecks_saga_pending_dispatch__
|
|
47
6
|
end
|
|
48
7
|
end
|